Rand() si mt_rand()

Thursday, 09 August, Year 4 d.Tr. | Author: Mircea Popescu

Rand() este generatorul de numere "aleatoare". Mt_rand() este un generator teoretic ceva mai bun, bazat pe abstractia numita Mersene Twister (de unde si mt_ acela), chestie asupra careia va documentati daca sunteti curiosi.

Prin documentatia implementarii in php apare urmatoarea alegatie :

Taking example from a note above i wanted to spot out the big difference between rand and mt_rand when producing images using randomness as noise.

for example this is a comparation between rand and mt_rand on a 400x400 pixel png:

mt_rand-rand

Asa cum se poate vedea, imaginea din stinga-i mult prea regulata pentru a se putea considera fie si-un inceput de implementare a unei functii aleatorii. Cit or fi de imposibila generarea de numere aleatoare prin procedee numerice, totusi ce se vede acolo-i mult sub limita cea mai de jos.

Chestia m-a frapat, asa ca m-am apucat ca omu' de stiinta s-o verific, scriind in acest scop doua programele :

I. rand.php

<?

header ('Content-Type: image/png');
$im = @imagecreatetruecolor(560,560) or die('You sir are a pickle!');

$red = imagecolorallocate ($im , 255 , 0 ,0);
$blue = imagecolorallocate ($im , 0,0,255);

for ($i = 0; $i <= 560; $i++) {
for ($j = 0; $j <= 560; $j++) {

if (rand(0,1) == 1) imagesetpixel ($im, $i, $j, $red);
else imagesetpixel ($im, $i, $j, $blue);

}
}

imagepng($im);
imagedestroy($im);

?>

Rezultatul :

mt_rand-rand-1

II. mt_rand.php

<?

header ('Content-Type: image/png');
$im = @imagecreatetruecolor(560,560) or die('You sir are a pickle!');

$red = imagecolorallocate ($im , 255 , 0 ,0);
$blue = imagecolorallocate ($im , 0,0,255);

for ($i = 0; $i <= 560; $i++) {
for ($j = 0; $j <= 560; $j++) {

if (mt_rand(0,1) == 1) imagesetpixel ($im, $i, $j, $red);
else imagesetpixel ($im, $i, $j, $blue);

}
}

imagepng($im);
imagedestroy($im);

?>

Rezultatul :

mt_rand-rand-2

Dupa cum puteti constata nu apar variatii semnificative, in tot cazul nu-i ceva comparabil cu ce sustine cetateanul. Am rulat chestia de mai multe ori, nu par sa apara diferente. E adevarat ca am folosit alt cod decit cel propus de el, dar pe de-o parte matematic vorbind se poate demonstra ca cele doua-s omoloage si in plus am incercat si codul lui fara sa rezulte nenorocirea aia din partea stinga.

Asa ca am ramas cumva confuz, eu eram ferm convins ca rand() e o solutie proasta, si cind colo se dovedeste ca nu-i pina la urma chiar asa de proasta. O fi strict chestiune de implementare concreta a rand() pe sistemul pe care-am testat ? E posibil (la rigoare e posibil ca rand() sa fie un alias pentru mt_rand() pina la urma) da' mi-e mult prea mult sa ma apuc sa instalez sisteme diferite ca sa verific atita lucru.

Totusi, daca cineva are dispozitia de-a face o proba, sunt curios de rezultate.

Category: AICMF
Comments feed : RSS 2.0. Leave your own comment below, or send a trackback.

9 Responses

  1. Mă uit diseară pe implementare și îți zic exact, da' momentan pot să speculez în felul următor: rand() ia random seed-ul din /dev/random sau /dev/urandom (mai degrabă din al doilea că e non-blocant) și eventual îl mai prelucrează un pic, după care aruncă rezultatul. mt_rand() face cam aceeași chestie pentru seed, atâta doar că folosește poliloghia cu Mersenne Twister pentru prelucrare.

    Acu' dacă device driver-ul care implementează /dev/urandom folosește și el tot un soi Mersenne Twister în spate - sau și mai bine, dacă are metode suficient de bune de a genera entropie -, rezultatele nu prea au cum să difere. Aici justificarea ar fi că dacă eu îmi dezactivez rețeaua, mouse-ul și altele (surse generatoare de întreruperi pentru procesor), calitatea generatorului aleator din sistemul de operare o să scadă semnificativ, fiindcă astea-s sursele de entropie folosite de /dev/random. Pe de altă parte dacă am o placă de rețea gigabit și în general multe dispozitive care generează multă informație, rand()-ul chior s-ar putea să ajungă la același nivel de calitate cu mt_rand().

    Chestia depinde evident și de implementarea propriu-zisă din kernel, însă mă îndoiesc că driver-ul s-a schimbat fundamental în timp.

  2. the differences reduce when reducing the pixels of the image.. infact for a 100x100 pixel image the noise produced from the rand function is much more realistic than how it is for a 400x400 image: http://oi39.tinypic.com/5k0row.jpg

    Ce citezi tu is opiniile lui X si Y, si deci cine zici ca-i acest "cyrax21 at gmail dot com" de-i luasesi de buna faza cu imaginea de 400px ? Cand chiar el zice imediat dupa ca rezultatele is neconsistente cand se schimba dimensiunile?

  3. Mircea Popescu`s avatar
    3
    Mircea Popescu 
    Thursday, 9 August 2012

    @spyked Aia suspectez si eu, exact. MT a fost o mare chestie prin 1999 sau cind, am ramas toti cu gura cascata (nu intr-un mod asa de diferit fata de cum am ramas - cel putin eu - cu gura cascata la bitcoin, aparent e ceva-n zona cripto care atrage mintile capabile sa te lase cu gura cascata), am impresia ca are atitia fani incit nu se mai poate pune problema sa fi ramas implementari de generatoare de numere aleatoare care sa nu fi fost rescrise sa includa MT.

    Nu m-ar mira sa fi fost rescris chiar random.c cindva in ultimii 10 ani, dat fiind ca iti amintesti mai vechea discutie cu "nu pot dom'le lasa puletii nimic in pace".

    Pe de alta parte teoria cu marea cantitate de entropie poate fi si ea valida pentru ca eu am rulat codul pe-un monstru. Ar fi bun de verificat pe ceva tableta scoasa din retea da' n-am la ora actuala lamp instalat pe nimic de-astea. Totusi... 250k cereri in sub 1 secunda, cam cit dracu' de intreruperi trebuia sa genereze ala ?!

    @Alex Mei, stiintele au asupra umanioarelor urmatorul avantaj semnificativ : e foarte simplu sa verificam orice sustinere stiintifica, cum se vede dinsus. Ca atare in stiinte nu conteaza "cine-i" ala ce sustine ceva. Aia conteaza la filosofie, de exemplu, unde nu te poti sui in autobuz sa faci doua statii pina-n ousia unde sa verifici divinitatea la coaie, are par sau are pene cum zice asta ?!

  4. Neah am verificat si eu tot la fel imi ies si mie. Cine stie ce minuni a facut tipul de pe php.net.

  5. Am dat o privire peste implementarea de PHP din depozit și rand()-ul de acolo îl apelează pe cel din C, care în principiu depinde de compilator, dar pe gcc sub Linux 100% accesează /dev/urandom. Cu toată tendențiozitatea o spun, io bănuiesc că individul de a postat aia rula PHP pe Windows, despre care nu știu nimic da' tind să cred (cu toată hatereala, cum ziceam) că aia-i sursa problemei. Aștept cu un interes ca un utilizator de Windoză să confirme sau să infirme teoria.

    Nu m-ar mira sa fi fost rescris chiar random.c cindva in ultimii 10 ani, dat fiind ca iti amintesti mai vechea discutie cu “nu pot dom’le lasa puletii nimic in pace”.

    E foarte posibil, da' cel puțin în ultimii șase ani nu pare a fi nimic semnificativ. M-am uitat pe un fork de kernel făcut acum câteva luni și cel mai mare patch în fișierul respectiv era unul de-al lui Torvalds de prin 2006, care modifica un comportament legat de rețea sau ceva asemănător. Individul de pe php.net a publicat observația în martie, când ar fi putut rula Linux 3.0, 3.2 sau în cel mai extrem caz 3.4, asta dacă nu cumva într-adevăr s-a apucat să testeze pe vreo distribuție antică, ceea ce s-ar lega de unele detalii cum ar fi scheduler-ul (care se activează și el la întreruperi de timer) folosit, care a fost rescris la un moment dat.

    Totusi… 250k cereri in sub 1 secunda, cam cit dracu’ de intreruperi trebuia sa genereze ala ?!

    Aici e discuție destul de lungă. Dispozitivele de rețea sunt printre puținele care pot genera un număr de întreruperi atât de mare încât să dea sistemul peste cap (prin stack overflow-uri în kernel sau alte dubiozități). Driverele de gigabit ethernet sigur recurg la fetch-uri adiționale pentru a limita numărul de întreruperi.

  6. Mircea Popescu`s avatar
    6
    Mircea Popescu 
    Thursday, 9 August 2012

    Cu toată tendențiozitatea o spun, io bănuiesc că individul de a postat aia rula PHP pe Windows, despre care nu știu nimic da’ tind să cred (cu toată hatereala, cum ziceam) că aia-i sursa problemei. Aștept cu un interes ca un utilizator de Windoză să confirme sau să infirme teoria.

    Ahahaha deci cit de sec pina in final :D

    Apropo de ultima chestie, ce zici tu e valid da' totusi mi se pare ca pentru nevoile discutiei curente putem cadea de acord ca numarul e totusi prea mare.

  7. Mirceo, o sa-ti fut amiralul in cur, cum ii place!
    Numai sa strang karma, sa pot posta.

    Al drac', retard!

  8. Mircea Popescu`s avatar
    8
    Mircea Popescu 
    Thursday, 9 August 2012

    Apai hai sa-ti dau noa.

  9. Frumos postul..pacat de injurii.

Add your cents! »
    If this is your first comment, it will wait to be approved. This usually takes a few hours. Subsequent comments are not delayed.