Newsgroup: it.comp.lang.c
Titolo: Random

Domanda da principiante: nella libreria standard esiste la funzione
int rand(void) che dovrebbe ritornare un numero casuale compreso tra 0
e RAND_MAX, ho provato ad usarla e mi ritorna sempre lo stesso numero,
ho provato sia sotto Win2k che sotto Linux.
Perchč?
Grazie.

"
da...@ciao.it
" ha scritto:

devi inizializzarla con un numero casuale:
su win & linux:
srand(time(0))
su linux:
  long seed; 
  FILE* dev;
 
  dev = fopen("/dev/urandom", "r");
  fread (&seed, sizeof(seed), 1, dev );
  fclose(dev);
  srand (seed);

Veramente non mi riferivo alla funzione 'int srand (int)', ma alla
rand, che non va inizializzata essendo definita come 'int rand
(void)'.
Bye.


 (void)'.
srand serve ad inizializzare rand, fidati.
se poi non ti vuoi fidare... fai come ti pare 

 (void)'.
Acido !!!
usa prima srand() per impostare il seed di rand() e poi chiama rand() come
gia' facevi...
Magari usa time() come base per il seed. (con srand())
Alex

Quindi vanno utilizzate tutte e due insieme?


 Quindi vanno utilizzate tutte e due insieme?
non insieme, prima srand(seed) e poi rand.
un consiglio: usa rand in questo modo:
int dado = 1 + (int)(6.0 * rand())/(RAND_MAX+1.0);

A questo punto la domanda nasce spontanea: perchè esiste una funzione
come rand se poi va usata per forza insieme a srand? Non potevano
inglobarla in srand o viceversa?
Ciao.


Non devi usarle per forza insieme...il fatto è che se usi rand da solo i
numeri randomizzati saranno gli stessi a ogni successivo avvio del
programma...cosa  che non capita usando srand prima...tutto qui
Enrico S.
--
Webmaster della Pagina NON Ufficiale del SonyCRX100
SonyCRX120,  SonyCRX140E/S, SonyCRX100EX, HP8100
HP8200, HP9100 & HP9200
http://www.freeweb.org/computer/SonyCRX100/

 inglobarla in srand o viceversa?
La funzione rand() usa algoritmi puramente deterministici per generare una
sequenza di numeri *apparentemente* casuali. La più semplice (e
statisticamente peggiore) implementazione è: y(i)=y(i-1)*a+b mod n.
E' evidente l'esigenza di dover partire da un valore iniziale della y, cioè
y(0); questo valore (chiamato seme) viene stabilito da srand(). Ma questa, a
sua volta, ha bisogno di essere chiamata passandogli un valore
sufficientemente variabile nel tempo, di solito si usa srand(time(NULL)).
Quindi, una volta chiamata srand(), puoi iniziare a chiamare rand() che
ritornerà numeri interi da 0 a RAND_MAX.
Il mio consiglio disinteressato è di evitare accuratamente l'uso di rand() e
simili (eccetto che nel compito in classe d'informatica) e di usare un serio
generatore di numeri pseudocasuali fra gli innumerevoli che puoi trovare
nella rete.
I motivi sono molti, se t'interessa, alcuni li puoi leggere facendo una
ricerca sul ng del c++.
Cristiano

 statisticamente peggiore) implementazione è: y(i)=y(i-1)*a+b mod n.
si puo' dimostrare che il termine b e' superfluo. che mi dici 
poidell'implementazione di lewis, goodman e miller del 69, che 
proposero il "minimal standard" RNG di questa forma?
te lo riporto, caso mai non lo conoscessi (difficile, dato che e' stato 
testato molto a lungo)
y(i+1) = (7^5) * y(i) mod (2^31 - 1)
che translato nella forma di Schrage per evitare overflow su macchinte 
con interi a 32 bit diventa:
a*y(i) mod m = a(y(i) mod m) - r*(int)(z/q)
all'espressione sopra va sommato m se il risultato e' minore di zero.
per i valori di cui sopra le costanti  q e r sono rispettivamente 
127773 e 2836
vi sono anche altri valori discussi per (a,q,r) che possono migliorare 
ulteriormente la diffusione statistica. 
sono 
(a,q,r) = (48271, 44488, 3399) e (69621, 30845, 23902)
il periodo del generatore e' m-2, abbastanza grande, imho, tranne se 
devi fare calcoli con il metodo montecarlo o simili, dove e' indicato 
usare altre funzioni.

 usare altre funzioni.
Il periodo è ancora migliore: m-1; se 2^31-2 è per te abbastanza grande...
meglio così!
Cristiano

 inglobarla in srand o viceversa?
No. Con srand() imposti il seme della funzione pseudo-casuale rand(). E'
importante perche' se vuoi ottenere, per ricostruire una condizione
particolare, la stessa sequenza di numeri pseudocasuali, ti basta chiamare
srand() con lo stesso seme che hai usato prima.
-- 
 Ciao, Bianco.
 Reply to luca.bianco (at) 
tiscalinet.it

 grande... meglio cosě!
va bene fino a che non si richiedono piu' di qualche milione di numeri 
casuali: ossia per la maggioranza delle applicazioni, credo.
Tra l'altro, seguendo la tua discussione sul ng di c++, sono andato a 
vedere i sorgenti della rand() di linux: usa in pratica la ran3 di NR, 
capitolo 7, con MBIG = 2^31-1 e alcuni accorgimenti suggeriti in 
seguito da knuth. la tabella non e' di 56 ma (di default) 128, e i 
puntatori sono spiazzati a seconda della dimensione.

 puntatori sono spiazzati a seconda della dimensione.
Ecco, allora ragioniamo su questo: secondo te ha senso usare tutto quel
codice, 128 long statiche più altre variabili statiche e temporanee per
avere un generatore con modulo 2^31-1, un periodo di lunghezza trascurabile
rispetto alla maggior parte dei generatori disponibili e un seme di 31 bit?
Ovviamente no!
Il generatore che ho postato l'altra volta (lfsr113) è incommensurabilmente
superiore a qualunque ran, rand, random di serie! Sotto qualunque punto di
vista. Includere quelle poche righe di codice nei programmi non costa nulla
è può evitare spiacevoli sorprese!
Come sempre, ognuno è libero di usare quello che vuole...
Cristiano

 Come sempre, ognuno č libero di usare quello che vuole...
esatto, tanto poi il codice migliore si seleziona da solo
 

Dove trovo tale algoritmo in C?
Se è cosi piccolino me lo riportate qui?
Ho cercato con Google e ho trovato solo roba per il Fortran.
Dome
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
PC Brain Official Web Site
http://digilander.iol.it/pcbrain
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

 e la ran3 e' garantito che fornisca "uniform standard deviate", quindi mi
basta e mi accontento
Chi si accontenta gode! Disse un tale. Ma di fronte all'evidenza...
Cristiano

 Chi si accontenta gode! Disse un tale. Ma di fronte all'evidenza...
vedremo, ti ho gia' detto che faro' come san tommaso (impegni 
permettendo) e lo spremero' per benino con test sui k-piani.

 di inserirlo come standard nella sua glibc.
Il fatto che venga usato da qualcuno non lo rende buono. Gl'ingegneri che
hanno implementato rand() sul Borland hanno fatto degli errori imperdonabili
rendendo un lcg peggiore di quello che è. Anche nel VC++ 6.0 viene usato un
lcg. Eppure sono fior d'ingegneri!
Il punto sul quale insisto è che se ti proponessero di comprare una Ferrari
allo stesso prezzo di una 500 nessuno al mondo comprerebbe la 500, male che
vada la Ferrari la rivendo (magari a metà prezzo) e mi ci compro quello che
mi pare.
Se puoi disporre a costo zero di un generatore dalle caratteristiche
eccezionalmente migliori di un altro non ha senso non usarlo!
La differenza tra i due paragoni è che tutti sanno la differenza tra una 500
e una Ferrari, ma pochi sanno capire e valutare la differenza tra due
generatori.
Cristiano

 ci compro quello che mi pare.
diciamo tra mercedes e ferrari, via...
comunque, vedremo.