Carissimi,
mi sono imbattuto in una stranezza che mi ha fatto perdere non poco tempo nella costruzione di un banale programmino per la generazione di numeri casuali interi compresi in un intervallo chiuso [a,b].
Come si sa possono essere ottenuti in due modi:
a) int casuale = (int) (b-a+1)*(rand()/(double)(RAND_MAX+1.0)) + a;
b) int casuale = rand()%(b-a+1) + a;
Ambedue i metodi sono validi ma se b è un divisore di RAND_MAX,la seconda metodologia porterebbe ad una distribuzione statistica non molto uniforme e di conseguenza è preferibile utilizzare la a).
Fin qui tutto ok.
Supposta l'inizializzazione del seme con srand(time(0));
ho lanciato le due righe di codice con entrambe le formulazioni.
Ebbene ad ogni run del programmino la prima forma ha sempre generato lo stesso numero la seconda no (se avessi aspettato un'ora il numero sarebbe uscito diverso).
Mi sono chiesto il perchè andando a piazzare delle stampe per capire dove fosse l'inghippo.
Ebbene il numero generato ad ogni lancio del programma con il primo metodo era ovviamente sempre diverso ma molto simile e la differenza sempre minore del centinaio (lo start della generazione è "quasi" il medesimo se i lanci sono ravvicinati).
Come dire ad ogni lancio il refresh del seme genera numeri di partenza vicini
Dividere quindi tale numero per (RAND_MAX +1.0) porta ad un decimale le cui cifre possono differire solo a partire dalla seconda,terza o quarta cifra decimale. Ecco spiegato il motivo del perchè gli interi in output risultavano uguali essendo interi.
Se invece frapponessi al primo metodo una rand() di "inizializzazione",il problema non si porrebbe e di conseguenza il numero generato nella successiva rand() risulterebbe totalmente "scorrelato" dalla prima, con conseguente risultato diverso ad ogni lancio dell'intero programma stesso (basta utilizzare per l'output il risultato della seconda rand()).
Nel modo b) invece non rilevo nessuna apparente difformità.
In soldoni per intervalli di generazione piccoli con estremo superiore non divisore di RAND_MAX è bene usare il secondo tipo, per altri il primo a meno che si abbia l'accortezza di inizializzare la randomizzazione con una generazione "inutilizzabile" in quanto in caso di run ravvicinati del programma la metodologia di scelta per il seme porta al primo numero del lotto molto simile tra due avvii distinti del software.
Mi chiedo se qualcuno sia giunto alle mia mia stessa analisi e/o si sia imbattuto in identiche problematiche arrivando a conclusioni diverse
Un saluto
A.
ps spero di essere stato abbastanza chiaro nell'esposizione