Newsgroup: it.comp.lang.c++
Titolo: rand() da' sempre gli stessi valori

Qualcuno sa spiegarmi perche' il mio stupido programmino di prova gira, ma
in realta' non serve a quasi nulla perche' i valori casuali restituiti da
rnd() sono sempre uguali e nella stessa sequenza (con linux cambiano i
numeri ma si ripetono anche li e sempre nella stessa sequenza).
Programmino:
#include <iostream.h>
#include <stdlib.h>
main ()
 {
   float gallons, liters;
   int x;
   x = 0;
   int casuale;
   float result;
     loop:;
     first:;
   casuale = rand();
     if (casuale > 100) goto first;
   cout << "insert gallons: ";
   cin >> gallons;
   liters = gallons * 3.7854;
   cout << "liters: "<< liters << '\n';
   result = casuale * liters;
   cout << "che moltiplicato per un numero a caso ovvero: "
    << casuale <<" fa: "
    << result << '\n';
   x++;
        if (x < 10) goto loop;
   return 0;
  }
Non c'e' un modo piu semplice per far si che il numero casuale sia compreso
tra x e y?
Grazie ciao.

rnd() sono sempre uguali e nella stessa sequenza 
Perche' rnd() non e' magica, ha bisogno di un "seme" di
inizializzazione.
Metti in cima al programm uno 
srand( time( NULL ) ) ;
Dopo aver incluso, ovviamente, time.h.

Andrea Laforgia wrote:

Ok, ora i numeri cambiano, ma perche' time?
E poi non c'e' un modo piu' semplice di assegnare una restrizione di valori al
numero casuale?
Suggerimento per chi alle prime armi come me:
Guida al C++ edito da McGrawHill e' molto poco esauriente, non compratelo!

Guida al C++ edito da McGrawHill e' molto poco esauriente, non compratelo!
beh, per questo bastava anche un K/R "Linguaggio C"..
ciao, Giacomo
-- 
| Giacomo Jack Tenaglia @ lab: tenaglia(at)
cs.unibo.it
 <--+
`---> Ultimate Player - Rock'n'Roll Lover - Linux Powered |

meglio del tempo (che scorre)..
non proprio. rand() non genera numeri casuali, ma pseudocasuali;
ovvero genera un nuovo numero a partire da quello precedente, secondo
delle ben determinate regole. Naturalmente ha bisogno di un primo
numero da cui partire per generare gli altri; questo è il seme. Se tu
non lo cambi ad ogni esecuzione il seme è sempre lo stesso e di
conseguenza anche la sequenza. Il modo migliore per cambiare seme ad
ogni esecuzione è basarsi sull'orario in cui è eseguito il programma.
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

 ogni esecuzione è basarsi sull'orario in cui è eseguito il programma.
Dunque, se ho ben capito se eseguo il programma alle 17,00 di tutti i giorni
la sequenza e' sempre la stessa?
Inoltre, prima di inizializzare il seme con time il default quale era
(curiosita')?

 tra x e y?
Più semplice di così! Questo sistema è semplicissimo quanto inefficiente:
l'orripilante rand() ritorna (di solito) numeri da 0 a 0x7FFF (tutt'altro
che pseudocasuali) e a te occorrono soltanto i primi 100!
Io credo che la seguente possa essere una risposta "standard" da inserire
nelle faq (magari con qualche modifica):
è vivamente da sconsigliare l'uso dell'orribile rand() eccetto i casi di
compito in classe d'informatica.
Si utilizzi *almeno* la seguente funzione (ULONG è unsigned long):
ULONG RND(void)
{
 static ULONG y=time(NULL);
 y=1664525L*y+1013904223L; // Numerical Recipes c7-1.pdf pag. 284
 return y;
}
le due costanti non devono essere modificate "a occhio" (un generatore così
semplice presenta più problemi di quanti se ne possano immaginare!).
Se si ha accesso ad un timer con una risoluzione migliore di time(), la
prima riga può essere modificata in:
 static ULONG y=time(NULL)^timer();
comunque suggerisco un generatore migliore come MT19937.
Se si necessita di numeri con una distribuzione uniforme da 0 a n-1 si
*deve* evitare RND()%n, si usi invece:
ULONG CASU(const ULONG n)
{
 const ULONG S=4294967296./n,X=S*n;
 ULONG x; if(X) { do x=RND(); while(x>=X); } else x=RND();
 return x/S;
}
se necessario si potranno aggiungere dei controlli per evitare divisioni per
zero o altro.
Per ottenere un numero da 0 a 100 con una distribuzione identica a RND() si
scriva CASU(101); un numero da "a" a "b" (con b>a) si ottiene facendo
CASU(b-a+1)+a.
Ciao
Cristiano

 la sequenza e' sempre la stessa?
No, dipende anche da quando lo hai acceso.
EMG



time() restituisce il numero di secondi trascorsi dalla
mezzanotte del 1/1/1970 al momento di cui viene eseguita.
Teoricamente si ottengono le stesse sequenze di numeri
casuali lanciando lo stesso programma contemporaneamente
su diversi computer (supponendo che il tempo necessario
per raggiungere la chiamata "time()" sia lo stesso e che
i computer abbiano gli orologi sufficientemente fasati).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 mezzanotte del 1/1/1970 al momento di cui viene eseguita.
Ops! Pardon. Comunque il succo non cambia: la sequenza non è la stessa
eseguendo il programma alle 17:00 di due giorni diversi.
EMG