2009-05-15 20 views
7

Quale sarebbe il modo più veloce per generare un gran numero di bit (pseudo-) casuali. Ogni bit deve essere indipendente ed essere zero o uno con uguale probabilità. Ho potuto ovviamente fare qualche variazione sulmodo più rapido per generare bit casuali

randbit=rand()%2; 

ma ritengo come ci dovrebbe essere un modo più veloce, generando più bit casuali da ogni chiamata al generatore di numeri casuali. Idealmente mi piacerebbe ottenere un int o un char in cui ogni bit è casuale e indipendente, ma sono anche possibili altre soluzioni.

L'applicazione non è di natura crittografica, quindi la casualità non è un fattore importante, mentre la velocità e la corretta distribuzione sono importanti.

+0

Quale distribuzione stai cercando? E quanto sei pignolo riguardo alla correttezza della distribuzione. Se vuoi veramente P [x] = 1/n per i numeri x nell'intervallo [1..n], hai comunque bisogno di un buon rng anche se la tua applicazione non è criptata. – AnnaR

+0

Che dire di qualcosa come '((int) rand * rand)% 2'? – C4u

risposta

3

Come dici tu generi solo numeri interi casuali.
Quindi avete 32 bit casuali con uno e zero tutti ugualmente probabili.

Ottenere i bit in un ciclo:

for (int i = 0; i < 32; i++) 
{ 
    randomBit = (randomNum >> i) & 1 
    ... 
    // Do your thing 
} 

Ripetere questo per tutte le volte è necessario per ottenere la giusta quantità di bit.

+1

rand non garantisce il ritorno di 32 bit casuali. Infatti, in msvc, restituisce solo 16. – avakar

+0

Ofcourse è dipendente dalla piattaforma ma il principio è sempre lo stesso indipendentemente dalla piattaforma. –

+2

Sono davvero equamente distribuiti? Ho considerato questa idea, ma non riuscivo a convincermi che ogni bit sarebbe stato distribuito in modo uguale e indipendente. – dagw

0

È possibile generare un numero casuale e continuare a shifitng destra e testare il bit meno significativo per ottenere i bit casuali invece di fare un'operazione mod.

5

convertire un numero casuale in binario
Perché non avere un solo numero (di dimensioni adeguate per ottenere abbastanza bit è necessario) e quindi convertirlo in binario. In realtà otterrai bit da un numero casuale, il che significa che sono anche casuali.

Gli zeri e quelli hanno anche la probabilità del 50%, poiché si prendono tutti i numeri compresi tra 0 e qualche limite 2^n e il conteggio del numero di zeri e di quelli sono uguali> il che significa che la probabilità di zeri e uno è la stessa.

per quanto riguarda la velocità
questo probabilmente sarebbe molto veloce, dal momento che ottenere solo un numero casuale rispetto al numero di bit in esso è più veloce. dipende solo dalla tua conversione binaria ora.

-3

Basta leggere un po 'di memoria - prendere una sezione n bit di memoria grezza. Sarà piuttosto casuale.

In alternativa, generare un int x casuale di grandi dimensioni e utilizzare solo i valori di bit.

for(int i = (bitcount-1); i >= 0 ; i--) bin += x & (1 << i); 
+3

memoria non contiene dati casuali, anzi in realtà: essi sono stati messi lì in modo strutturato da un'applicazione. – soulmerge

+0

I bit saranno disposti in modo casuale a tutti gli effetti, poiché la struttura è rilevante per il significato. per esempio. "my dog" è un dato ordinato, ma il suo file binario è 011011010111100100100000011001000110111101100111, che è piuttosto casuale. Per favore restituiscimi il mio +1 poiché sono corretto. –

+3

Prendere la memoria grezza in generale non è una buona idea! Per esempio. nell'esempio di una stringa ASCII, ogni 8 bit è 0, poiché i caratteri validi utilizzano solo i 7 bit più bassi. Inoltre, sembra che i byte di 0 siano abbastanza comuni (padding, memoria inutilizzata, numeri che non utilizzano l'intervallo completo, bool memorizzati in int32, ...) quindi potresti aspettarti più 0 e poi 1 s. – Chris

0

Se Rememeber correttamente, i bit meno significativi sono normalmente avendo un "meno casuale" distribuzione per più pseuodo generatori di numeri casuali, in modo da utilizzare modulo e/o ogni bit del numero generato sarebbe male se sono preoccupati per la distribuzione.

(Forse si dovrebbe almeno google quello che dice Knuth ...)

Se che tiene (e la sua difficile dire senza sapere esattamente cosa si sta utilizzando l'algoritmo) basta usare il più alto bit in ogni numero generato.

http://en.wikipedia.org/wiki/Pseudo-random

0

Quanto grande cosa avete bisogno il numero di bit generati per essere? Se non è più grande di un paio di milioni, e tenendo presente che non si sta utilizzando il generatore per la crittografia, quindi penso che il modo più veloce possibile sarebbe quella di precompute un grande insieme di numeri interi con la distribuzione corretta, convertirlo in un testo file in questo modo:

unsigned int numbers[] = 
{ 
    0xABCDEF34, ... 
}; 

e quindi compilare la matrice nel vostro programma e passare attraverso di essa un numero alla volta.

In questo modo si ottengono 32 bit per ogni chiamata (su un processore a 32 bit), il tempo di generazione è il più breve possibile perché tutti i numeri vengono generati in anticipo e la distribuzione è controllata dall'utente. Il rovescio della medaglia è, naturalmente, che questi numeri non sono affatto casuali, che a seconda di ciò che si sta usando il PRNG potrebbero non avere importanza.

2

Ecco uno molto veloce ho codificato in Java sulla base di un algoritmo XORShift di George Marsaglia: si ottiene 64 bit alla volta!

/** 
* State for random number generation 
*/ 
private static volatile long state=xorShift64(System.nanoTime()|0xCAFEBABE); 

/** 
* Gets a long random value 
* @return Random long value based on static state 
*/ 
public static final long nextLong() { 
    long a=state; 
    state = xorShift64(a); 
    return a; 
} 

/** 
* XORShift algorithm - credit to George Marsaglia! 
* @param a Initial state 
* @return new state 
*/ 
public static final long xorShift64(long a) { 
    a ^= (a << 21); 
    a ^= (a >>> 35); 
    a ^= (a << 4); 
    return a; 
} 
+0

Nota: il motivo per cui questo algoritmo è così veloce è che utilizza solo semplici operatori bit a bit, in una sequenza che è stata dimostrata (Marsaglia) per generare una sequenza casuale psuedo "abbastanza buona". Questo * non * è crittograficamente forte ma è abbastanza buono per giochi, simulazioni ecc. – mikera

0

se avete solo bisogno di un po 'alla volta provare bool coinToss() { return rand()&1; } Si sarebbe tecnicamente un modo più veloce per generare i bit a causa della sostituzione del% 2 con un & 1 che sono equivalenti.

Problemi correlati