2010-07-01 12 views
8

gcc 4.4.4 c89utilizzando rand per generare numeri casuali

Sto usando il codice qui sotto. Tuttavia, continuo a ricevere lo stesso numero:

size_t i = 0; 

    for(i = 0; i < 3; i++) { 
     /* Initialize random number */ 
     srand((unsigned int)time(NULL)); 
     /* Added random number (simulate seconds) */ 
     add((rand() % 30) + 1); 
    } 

Mi piacerebbe ricevere da 0 a 30 restituiti. Tuttavia, l'ultima volta che ho eseguito questo ho ottenuto 17 tre volte.

Molte grazie,

+2

possibile duplicato del [funzione di numeri casuali è cilecca] (http: // StackOverflow.it/questions/1068350/random-number-function-is-misfiring) –

risposta

22

Stai semina all'interno il ciclo (con lo stesso valore a causa di quanto velocemente verrà eseguito il loop), che fa sì che il numero casuale generato per essere lo stesso ogni volta.

è necessario spostare la vostra funzione di semi di fuori loop:

/* Initialize random number */ 
srand((unsigned int)time(NULL)); 

for(i = 0; i < 3; i++) { 
    /* Added random number (simulate seconds) */ 
    add((rand() % 30) + 1); 
} 
9

È necessario chiamare srand solo una volta, all'inizio del programma.

srand inizializza il generatore di numeri pseudo casuali utilizzando il tempo in secondi. Se lo si inizializza con un numero particolare, si otterrà sempre la stessa sequenza di numeri. Ecco perché di solito si desidera inizializzarlo all'inizio utilizzando l'ora (in modo che il seed sia diverso ogni volta che si esegue il programma) e quindi utilizzare solo rand per generare numeri che sembrano casuali.

Nel tuo caso il tempo non cambia da iterazione a iterazione, poiché la sua risoluzione è di appena 1 secondo, quindi ottieni sempre il primo numero della sequenza pseudo-casuale, che è sempre la stessa.

+1

È proprio vero che 'è necessario chiamare srand una sola volta, all'inizio del programma?»? Voglio dire, penso che se uno ha bisogno dovrebbe chiamare 'srand' ogni volta che ha bisogno di cambiare il seme del generatore di numeri casuali e ottenere una sequenza diversa di numeri casuali? –

+0

È vero per questo particolare pezzo di codice;). Ovviamente, puoi chiamarlo ogni volta che vuoi cambiare il seme per qualche motivo; non è proibito –

+0

@skwllsp e di solito solo una volta _per richiesta_! – alexanderpas

4

È necessario eseguire srand((unsigned int)time(NULL)) una sola volta prima del ciclo.

2

È completamente possibile che le 3 volte 17 siano ancora completamente casuali.

C'è una probabilità di circa 1 su 10 di ottenere due numeri uguali quando si utilizza un intervallo da 1 a 30 e tre scelte. (questo è dovuto allo birthday problem)

Ora, ottenere tre risultati identici ha ancora una probabilità di 1 su 900 utilizzando lo stesso intervallo.

si potrebbe desiderare di leggere più di fondo sul analysis page of random.org

+0

In questo caso (anche se non si trattava di un errore di codifica) ottenendo due 17 in una riga non ha nulla a che fare con il problema del compleanno. Partendo dal presupposto che ogni numero casuale è indipendente, calcolare la probabilità di ottenere due 17 di fila sarebbe 1/30 * 1/30 o 1/900. Per tre sarebbe 1/30 * 1/30 * 1/30 o 1/27000. – MarkD

+0

ma dimentichi che ci sono 30 diverse possibilità di ottenere tre numeri uguali. 1/27000 * 30 = 1/900 – alexanderpas

+0

ora, per i due lo stesso ... ci sono in realtà tre combinazioni XYX, XXY e YXY con 30 possibilità ciascuna. 1/900 * 30 = 1/30 * 3 = 3/30 = 1/10 – alexanderpas

1

seme al generatore di numeri pseudo casuali dovrebbe essere chiamato solo una volta al di fuori del ciclo. Usare il tempo come seme è una buona cosa. Tuttavia c'è ancora la possibilità di ottenere lo stesso numero casuale.

1

Suggerisco piuttosto di utilizzare anche la chiamata di sistema gettimeofday() per recuperare il seed da utilizzare per alimentare srand().

Qualcosa di simile

 

struct timeval tv; 
... 
gettimeofday(&tv, NULL); 
srand(tv.tv_usec); 
... 
 

Questo approccio può aggiungere più entropia nel codice generazione di numeri pseudo. IMHO ovviamente

Ciao ciao