Má někdo zkušenosti s naprogramováním generátoru náhodných čísel v Mosaicu?
Asi se mi budou hodit všechny nápady jaký vás napadnou.
Pokud to neni opravdu nutne, tak se pouzivaji generatory psedonahodnych cisel. Tj. zvenku se tvari jako nahodne, ale jejich posloupnost je predem dana.
Maji tu vyhodu, ze v pripade chyby v programu, je mozne cely proces otestovat.
Mezi nejjednodusi patri posuvny register + XOR hradlo z nekterych z poslednich bitu.
Kratke pojednani treba zde:
http://www.kemt.fei.tuke.sk/predmety/KEMT414_AK/_materialy/Cvicenia/kryp_4.pdf
http://en.wikipedia.org/wiki/Random_number_generation
Ukazka kodu (netestoval jsem to):
m_w = <choose-initializer>; /* must not be zero */
m_z = <choose-initializer>; /* must not be zero */
uint get_random()
{
m_z = 36969 * (m_z & 65535) + (m_z >> 16);
m_w = 18000 * (m_w & 65535) + (m_w >> 16);
return (m_z << 16) + m_w; /* 32-bit result */
}
Zajisteni opravdu nahodneho generatoru je velmi slozite bez specialniho HW.
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
Zatím děkuji za inspiraci pokusím se to použít.
Použil jsem tohle:
Random : UDINT;
Random := MOD(Random*214013 + 2531011, 16777216); // Random generator
Odzkoušeno.