2010-10-15 19 views
12

Sto scrivendo un programma che scrive test statistici in Delphi (deve essere Delphi) e ho sentito dire che la funzionalità Random è piuttosto strana. Devi chiamare randomize per randomizzare il seme della funzione casuale all'avvio del programma.Quanto è affidabile la funzione casuale in Delphi

Mi chiedo se la funzione casuale (dopo aver chiamato randomize) sia abbastanza casuale per test statistici o un twister Mersenne sia necessario? Qualcuno ha qualche idea sull'implementazione reale casuale che può dirmi quanto sia importante questo?

+4

Avere per inizializzare una funzione Randomizer è non è affatto raro - devi fare la stessa cosa con un tornado di Mersenne. –

+1

E la possibilità di avviare una funzione casuale è spesso un grande vantaggio. Utilizzando lo stesso seme è possibile duplicare i risultati, che possono essere di grande aiuto, ad esempio durante il debug. –

+1

C'è un'eccellente discussione su questo argomento nel capitolo 6 del libro di Julian Bucknall "Tomes of Delphi: Algorithms And Data Structures" (www.boyet.com) –

risposta

6

Se il Random è sufficientemente affidabile per i test statistici, dipende dal contesto in cui si intende utilizzarlo.

Detto questo, ho scritto diversi pezzi di codice Delphi che hanno bisogno di fare statistiche corrette, e ho usato Random ad es. per ottenere varie distribuzioni null, pseudo-repliche di dati e resamplings. Finora, non mi sono imbattuto in alcun caso nel mio codice in cui Random avrebbe prodotto risultati distorti o inaffidabili, o risultati che avrebbero precluso il suo uso per il test statistico previsto. Ma ciò che vale per il mio codice non deve necessariamente valere per il tuo.

In caso di dubbio, è possibile analizzare statisticamente i risultati delle chiamate allo Random (ad esempio in R, SPSS, ecc.) Ed esaminare se la distribuzione dei risultati viola i requisiti di distribuzione per i propri test statistici particolari. [Se sei un vero scienziato, questo è quello che dovresti fare comunque.]

Se hai bisogno di altri PRNG - e.g. la libreria TPMath contiene alcuni. (Per le cose più coinvolti, c'è anche la possibilità di chiamare funzioni statistiche elaborate da R via Delphi.)

4

A meno che non si acquisti un hardware relativamente esoterico, la migliore approssimazione ai numeri casuali che un computer può fornire è una sequenza pseudocasuale completamente deterministica. In generale, la funzione randomize usa un valore relativamente casuale (spesso basato sul tempo, ma a volte sui movimenti del mouse - non ho idea di cosa faccia Delphi) come seme che fornisce il punto di ingresso alla sequenza pseudocasuale. Senza questo, finirai per ricomprare lo stesso insieme di numeri casuali nello stesso ordine ogni volta, il che tende a vanificare lo scopo di usare numeri casuali in primo luogo.

Ok, mi rendo conto che questo non risponde alla domanda sull'affidabilità, ma dovrebbe darti una certa sicurezza che richiedere di chiamare randomize è un segno di un buon generatore piuttosto che di uno cattivo. Ci sono un sacco di test statistici che mostrano quanto sia casuale una sequenza di numeri, ed è probabile che il generatore di numeri casuali Delphi sia adatto a molti scopi in quanto è un prodotto maturo.

16

alt text

non ho potuto resistere.

+2

Mi piace l'umorismo. Ma deve ** essere in CW! –

+1

Nah, no CW, illustra perfettamente che ciò che possiamo percepire come non casuale, in realtà può essere perfettamente casuale. Dopotutto, casuale non è l'assenza di un modello ... –

+1

Ogni volta che ti senti incline a mettere "Non potrei resistere" nella tua "risposta", dovresti essere incline a farlo in CW. È una questione di grado, ma in questo caso non c'era una risposta diretta all'OP. – Argalatyr

20

Il PRNG di Delphi, come quasi tutti i PRNG RTL in linguaggio di programmazione, è un linear congruential generator.

È abbastanza buono per la maggior parte delle cose su piccola scala, ma ci sono cose a cui fare attenzione. In particolare, fai attenzione ai bit di basso ordine: il modello di moltiplicazione e aggiunta indica che i bit di basso ordine non sono affatto casuali. Ma questo generalmente si applica solo ai grandi valori a 32 bit estratti e quindi troncati con mod o simili. L'utilizzo di Random(10) per prelevare un valore compreso tra 0 e 9 utilizza internamente una moltiplicazione sull'intero intervallo a 32 bit anziché su un'operazione mod.

2

Dal sito web Embarcadero:

_lrand è la lunga funzione di generatore di numeri casuali. _rand utilizza un moltiplicatore di numeri casuali congruenti con periodo 2^64 per restituire numeri pseudo casuali successivi nell'intervallo da 0 a 2^31 - 1.

Il generatore viene reinizializzato chiamando srand con un valore argomento di 1. Può essere impostato su un nuovo punto di partenza chiamando srand con un numero seme specificato.

2

Se non cambiare l'attuazione dal momento che ho analizzato (Delphi 4 IIRC), il Delphi PRNG è implementato in questo modo:

Randseed:=int32(Randseed*$08088405)+1 
result:=Randseed*Range shr 32 

(pseudocodice/assumere le moltiplicazioni sono arbitrariamente grandi numeri interi)

3

Solo per aumentare il numero di possibilità: Windows offre una gamma di Cryptography functions integrata. Probabilmente c'è anche un wrapper Delphi per loro, se non è già incluso di default.

Tra queste funzioni è anche un cryptographically strong random number generator. Questa è di gran lunga la migliore casualità che si otterrà nel software, perché si basa su una lunga lista di fattori. Non sono sicuro, ma ho il sospetto che userà anche un generatore di numeri casuali dell'hardware se ne hai uno.

E se ciò non bastasse, puoi anche provare ad iscriverti allo per alcuni valori casuali REALMENTE.

-1

ritorno casuale tra 0..9

StrToInt(copy(FloatToStr(Random),4,1)) 

Nota: Controllare FloatToStr (casuale) di lunghezza prima dell'uso o utilizzare alcun altra cifra dalla parte decimale ...

+1

La chiamata consigliata per generare un numero intero casuale nell'intervallo da 0 a 9 è "random (10)" L'uso di floattostr è intelligente, ma l'espressione data a volte fallirà. Considerare: "randseed: = -1498392781; X: = StrToInt (copia (FloatToStr (Random), 4,1));" In questo caso random restituirà esattamente 0.5, floattostr restituirà "0.5", poiché non esiste un quarto carattere, la copia restituirà una stringa vuota e StrToInt fallirà con un'eccezione. –

+0

L'idea era di dare un esempio con una dispersione maggiore (si veda [collegamento] (http://stackoverflow.com/a/3947122/636542). Così si può migliorare liberamente questo algoritmo in base alle proprie esigenze ... – DejanR

Problemi correlati