Pokud stačí psedonáhodné číslo, zde je kód přepsaný z Cčka do ST, který lze v PLC využít. Funkce r4_uniform_01 vrací čísla s rovnoměrným rozdělením. Funkční blok r4_normal_01 vrací čísla s pseudonormální
m rozdělením, stejně jako r4_normal, který má navíc parametr pro střední hodnotu a odchylku.
FUNCTION r4_uniform_01 : REAL
(*
R4_UNIFORM_01 returns a unit pseudorandom R4.
This routine implements the recursion
seed = 16807 * seed mod ( 2**31 - 1 )
r4_uniform_01 = seed / ( 2**31 - 1 )
The integer arithmetic never requires more than 32 bits,
including a sign bit.
If the initial seed is 12345, then the first three computations are
Input Output R4_UNIFORM_01
SEED SEED
12345 207482415 0.096616
207482415 1790989824 0.833995
1790989824 2035175616 0.947702
*)
VAR_INPUT
init_seed : BOOL;
END_VAR
VAR
k : DINT;
END_VAR
VAR_IN_OUT
seed : DINT;
END_VAR
VAR_EXTERNAL
AT %SL52 : DINT;
END_VAR
if init_seed then
seed := %SL52;
end_if;
k := seed / 127773;
seed := 16807 * ( seed - k * 127773 ) - k * 2836;
IF seed < 0 THEN
seed := seed + 2147483647;
END_IF;
//
// Although SEED can be represented exactly as a 32 bit integer,
// it generally cannot be represented exactly as a 32 bit real number!
//
r4_uniform_01 := DINT_TO_REAL(seed) * 4.656612875E-10;
END_FUNCTION
FUNCTION_BLOCK r4_normal_01
(*
R4_NORMAL_01 returns a unit pseudonormal R4.
The standard normal probability distribution function (PDF) has
mean 0 and standard deviation 1.
The Box-Muller method is used, which is efficient, but
generates two values at a time.
*)
VAR_IN_OUT
seed : DINT;
END_VAR
VAR CONSTANT
PI : REAL := 3.141592653589793;
END_VAR
VAR
used : DINT := -1;
seed2 : DINT;
y : REAL;
r1, r2 : REAL;
END_VAR
VAR_OUTPUT
x : REAL;
END_VAR
IF ( used = -1 ) THEN
used := 0;
END_IF;
//
// If we've used an even number of values so far, generate two more, return one,
// and save one.
//
IF used MOD 2 = 0 THEN
r1 := r4_uniform_01 ( false, seed );
seed2 := seed;
r2 := r4_uniform_01 ( false, seed2 );
x := sqrt ( -2.0 * log ( r1 ) ) * cos ( 2.0 * PI * r2 );
y := sqrt ( -2.0 * log ( r1 ) ) * sin ( 2.0 * PI * r2 );
//
// Otherwise, return the second, saved, value and the corresponding
// value of SEED.
//
ELSE
x := y;
seed := seed2;
END_IF;
used := used + 1;
END_FUNCTION_BLOCK
FUNCTION_BLOCK r4_normal
(*
R4_NORMAL returns a scaled pseudonormal R4.
The normal probability distribution function (PDF) is sampled,
with mean A and standard deviation B.
*)
VAR
i_r4_normal_01 : r4_normal_01;
END_VAR
VAR_INPUT
a : REAL;
b : REAL;
END_VAR
VAR_IN_OUT
seed : DINT;
END_VAR
VAR_OUTPUT
x : REAL;
END_VAR
i_r4_normal_01(seed := seed);
x := a + b * i_r4_normal_01.x;
END_FUNCTION_BLOCK