2011-11-08 22 views
16

Ho appena scoperto che il srand(1) ripristina il PRNG di C (++) allo stato prima di qualsiasi chiamata a srand (come definito nello reference). Tuttavia, il seme 0 sembra fare lo stesso, o lo stato prima di qualsiasi chiamata a srand sembra utilizzare il seme 0. Qual è la differenza tra queste due chiamate o qual è la ragione per cui fanno la stessa cosa?Qual è la differenza tra srand (1) e srand (0)

Per esempio questo codice (execute on Ideone)

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    for (int seed = 0; seed < 4; seed++) { 
     printf("Seed %d:", seed); 
     srand(seed); 
     for(int i = 0; i < 5; i++) 
      printf(" %10d", rand()); 
     printf("\n"); 
    } 
    return 0; 
} 

rendimenti

Seed 0: 1804289383  846930886 1681692777 1714636915 1957747793 
Seed 1: 1804289383  846930886 1681692777 1714636915 1957747793 
Seed 2: 1505335290 1738766719  190686788  260874575  747983061 
Seed 3: 1205554746  483147985  844158168  953350440  612121425 
+1

Domanda molto interessante. A mia conoscenza, srand non ha alcun valore "magico", ma rand() è semplicemente inizializzato su un seme di 1, e quindi inizia con quel seme a meno che non venga detto qualcosa di diverso. Il che significherebbe implicitamente che se chiamate srand (1), "resettate allo stato originale". Comunque, l'output che hai postato suggerisce che in realtà "resetta magicamente" al seed 0 che avevi impostato prima, non a 1 (che, btw, la mia implementazione non fa). – Damon

risposta

11

È probabilmente un dettaglio di implementazione. Lo standard impone che il seme casuale 1 sia speciale e il registro interno dell'algoritmo del generatore casuale specifico è probabilmente inizializzato a zero, causando così la stessa sequenza casuale per seme (0) e seme (1). Mi piacerebbe anche scommettere che la prima riga del tuo srand() implementazione assomiglia:

if (seed == 1) seed = 0; 

per forzare il comportamento conforme agli standard.

Generalmente, i generatori di numeri casuali per rand() e srand() non sono necessari per fornire sequenze diverse per semi diversi, ma la stessa sequenza per lo stesso seme. Quindi, non fare affidamento su semi diversi generando sequenze casuali diverse, e dovresti stare bene. In caso contrario, benvenuto al divertimento specifico dell'implementazione.

+9

In realtà, il codice è più simile a 'if (seed == 0) seed = 1;', poiché l'algoritmo utilizzato dall'implementazione GNU di 'rand()' non funziona con un seed di zero. –

7

Né il C né il C++ standard dicono molto sulle specifiche di attuazione di rand() e srand(). I dettagli sono lasciati quasi interamente all'attore. Lo standard C richiede che:

Se srand viene quindi chiamato con lo stesso valore di inizializzazione, la sequenza di numeri pseudo casuali deve essere ripetuta. Se Rand viene chiamato prima delle chiamate a srand sono stati fatti, la stessa sequenza è generato come quando srand viene dapprima chiamato con un valore di seme di 1.

ma non contiene alcun requisito che diverse semi deve produrre diverse sequenze. Apparentemente, sul tuo sistema, i semi di zero e uno hanno lo stesso effetto. Immagino che questo sia per garantire la retrocompatibilità con qualche pezzo di software che si aspetta che srand(0) ripristini il PRNG al suo stato iniziale.

0

Durante la lettura di pagine di manuale, tutti indicano che "Se non viene fornito alcun valore di inizializzazione, la funzione rand() viene automaticamente inizializzata con il valore 1". Questo è probabilmente il motivo per cui la pagina di riferimento che si collega dichiara che seeding con 1 reimposta lo stato.

Che lo stesso risultato si verifichi per il seeding con entrambi 0 e 1 è molto probabilmente dipendente dall'implementazione, e non dovrebbe essere conteggiato su tutte le piattaforme.

0

La funzione srand() utilizza l'argomento come seme per una nuova sequenza di numeri pseudo-casuali da restituire dalle successive chiamate a rand(). Se srand() viene quindi chiamato con lo stesso valore di seme, la sequenza di numeri pseudo casuali deve essere ripetuta. Se rand() viene chiamato prima che vengano effettuate chiamate a srand(), la stessa sequenza deve essere generata quando srand() viene chiamato per la prima volta con un valore di inizializzazione di 1.

Forse utile: http://pubs.opengroup.org/onlinepubs/009695399/functions/rand.html

1

Se seme è impostato su 1, il generatore viene reinizializzato al valore iniziale e produce gli stessi valori prima di ogni chiamata a rand o srand. tratto dal srand di riferimento

15

Come glibc fa:

around line 181 of glibc/stdlib/random_r.c, funzione __srandom_r

/* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */ 
    if (seed == 0) 
    seed = 1; 

all'interno Ma questo è solo come glibc fa. Dipende dall'implementazione della libreria standard C.

-3

Il motivo 1 è specificato perché alcuni generatori di numeri casuali si bloccheranno a zero se il seme è impostato su zero. Ad esempio registri a scorrimento e tipi congruenti moltiplicativi, ovvero r(n+1) = (A * r(n))mod M.

Molte implementazioni C utilizzano lineare congruenziale r(n+1) = (A * r(n) + B) mod M, B <> 0 che non si blocca.

+0

Cosa c'entra questo con la domanda? – melpomene

Problemi correlati