2015-08-10 14 views
30

Ho due domande dell'attuazione di Random classe .NET Framework 4.6 (codice disponibile here):Qual è la qualità dell'implementazione della classe Random in .NET?

  1. Qual è la logica per l'impostazione Seed argomento 1 alla fine del costruttore? Sembra essere copiata da Ricette numeriche in C (2nd Ed.) dove ha un senso, ma non ne ha in C#.

  2. È direttamente affermato nel libro che inextp campo è impostato al valore 31 perché (Numerical Recipes in C (2nd Ed).):

La costante 31 è speciale; vedi Knuth.

Tuttavia, nell'implementazione .NET questo campo è impostato sul valore 21. Perché? Il resto di un codice sembra seguire da vicino il codice del libro ad eccezione di questo dettaglio.

+6

Dov'è @EricLippert se hai bisogno di lui? –

+1

* Tuttavia, nell'implementazione .NET questo campo è impostato sul valore 21. Perché? * Hanno appena scelto un numero casuale;) –

+2

Inoltre, c'è un MZ costante che non viene utilizzato affatto, invece il valore '0' è semplicemente usato in quei posti. –

risposta

23

Riguardo al problema intexp, si tratta di un bug, uno dei quali Microsoft has acknowledged and refused to fix a causa di problemi di compatibilità con le versioni precedenti.

In effetti, hai scoperto un vero problema con l'implementazione Random. Ne abbiamo discusso all'interno del team e con alcuni dei nostri partner e abbiamo concluso che purtroppo non possiamo risolvere il problema al momento. Il motivo è che alcune applicazioni si basano sul fatto che, quando inizializzato con lo stesso seme, il generatore produce la stessa sequenza pseudo casuale. Anche se il cambiamento è positivo, interromperà le applicazioni che hanno fatto questa ipotesi una volta migrate alla versione "fissa".

+0

Non capisco perché il generatore non produca più la stessa sequenza pseudo casuale con lo stesso seme se si imposta 'intexp' su' 31' invece di '21'. –

+4

L'algoritmo mantiene un buffer di 56 numeri interi casuali che vengono inizializzati in base al valore seme. Due indici nel buffer dovrebbero essere mantenuti a una distanza di 31 posizioni (21 in questo caso), il numero pseudo-casuale viene calcolato come la differenza dei valori su questi indici. Non è possibile modificare la posizione degli indici senza modificare l'output poiché farebbero riferimento a valori diversi. – DGibbs

+1

@TimSchmelter: con la nuova implementazione '31' produrrà una sequenza diversa dall'implementazione' 21'. Per semplificare estremamente, Random.next() è una funzione del seme e del valore 31 o 21. cambia il valore, cambia il comportamento di 'next'. – njzk2

5

Per un po 'di contesto:

Qualche tempo fa ho pienamente analizzato questa implementazione. Ho trovato alcune differenze.

A il primo (perfettamente fine) è un diverso valore grande (MBIG). Numerical Recipies afferma che Knuth chiarisce che qualsiasi grande valore dovrebbe funzionare, quindi non è un problema, e Microsoft ha ragionevolmente scelto di utilizzare il valore più grande di un intero a 32 bit.

La seconda era quella costante, hai menzionato. Quello è un grosso problema. Nel minimo diminuirà sostanzialmente il periodo. Ci sono state segnalazioni che gli effetti sono in realtà peggiori di così.

Ma poi arriva un'altra differenza particolarmente sgradevole. Si è letteralmente garantito di polarizzare l'output (poiché lo fa direttamente), e probabilmente influenzerà anche il periodo del RNG.

Quindi, qual è questo secondo problema? Quando .NET è uscito per la prima volta, Microsoft non si è resa conto che l'RNG che codificava era inclusivo alle due estremità e lo hanno documentato come esclusivo alla fine massima. Per risolvere il problema, il team addetto alla sicurezza ha aggiunto una riga di codice piuttosto malvagia: if (retVal == MBIG) retVal--;. Questo è molto sfortunatamente dato che la correzione corretta sarebbe letteralmente solo 4 caratteri aggiunti (più spazi bianchi).

la correttezza correzione sarebbe stata cambiare MBIG-int.MaxValue-1, ma passa Sample() utilizzare MBIG+1 (vale a dire continuare a utilizzare int.MaxValue). Ciò garantirebbe che quel Campione abbia il range [0.0, 1.0) senza introdurre alcun bias, e cambia solo il valore di MBIG che le Ricette Numeriche hanno detto che Knuth ha detto che è perfettamente a posto.

Problemi correlati