Název: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Crossi 26.08.2013, 21:47
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.
Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Slavomír Skopalík 26.08.2013, 22:04
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.
Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Milan Bydžovský 27.08.2013, 13:13
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
Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Crossi 28.08.2013, 00:05
Zatím děkuji za inspiraci pokusím se to použít.
Název: Re: Jak v Mosaicu generovat náhodná čísla?
Přispěvatel: Erhard Mareček 04.09.2013, 10:01
Použil jsem tohle:
Random : UDINT;
Random := MOD(Random*214013 + 2531011, 16777216); // Random generator
Odzkoušeno.
|