2009-05-15 37 views
7

¿Cuál sería la forma más rápida de generar una gran cantidad de bits (pseudo) aleatorios? Cada bit debe ser independiente y ser cero o uno con la misma probabilidad. Yo, obviamente, podría hacer alguna variación enforma más rápida de generar bits aleatorios

randbit=rand()%2; 

pero siento que debe haber una manera más rápida, generando varios bits aleatorios de cada llamada al generador de números aleatorios. Idealmente me gustaría obtener un int o un char donde cada bit es aleatorio e independiente, pero también son posibles otras soluciones.

La aplicación no es de naturaleza criptográfica, por lo que la aleatoriedad fuerte no es un factor importante, mientras que la velocidad y la distribución correcta es importante.

+0

¿Qué distribución estás buscando? Y qué exigente eres sobre la corrección de la distribución. Si realmente quiere P [x] = 1/n para los números x en el intervalo [1..n], entonces aún necesita un buen rng, incluso si su aplicación no es crypto. – AnnaR

+0

¿Qué tal algo como '((int) rand * rand)% 2'? No se garantiza que – C4u

Respuesta

3

Como dices solo generas enteros aleatorios.
Luego tienes 32 bits aleatorios con unos y ceros igualmente probables.

Obtener los bits en un bucle:

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

Repita esto para el mayor número de veces que se necesita para obtener la cantidad correcta de bits.

+1

rand devuelva 32 bits aleatorios. De hecho, en msvc, solo devuelve 16. – avakar

+0

Por supuesto, depende de la plataforma, pero el principio sigue siendo el mismo independientemente de la plataforma. –

+2

¿Están realmente distribuidos equitativamente? Consideré esta idea, pero no pude convencerme a mí mismo de que cada parte se distribuiría por igual e independientemente. – dagw

0

Puede generar un número aleatorio y seguir shifitng derecha y probar el bit menos significativo para obtener los bits aleatorios en lugar de hacer una operación mod.

5

convertir un número binario de azar en
Por qué no conseguir un solo número (del tamaño apropiado para obtener suficientes bits que necesita) y luego convertirlo a binario. Obtendrás bits de un número aleatorio, lo que significa que también son aleatorios.

Los ceros y unos también tienen la probabilidad del 50%, ya que tomar todos los números entre 0 y algunos 2^n limitar y contar el número de ceros y unos es igual> lo que significa que la probabilidad de ceros y unos es la misma.

respecto a la velocidad
esto sería probablemente muy rápido, ya que acaba de conseguir un número aleatorio en comparación con el número de bits en el que es más rápido. simplemente depende de tu conversión binaria ahora.

-3

Simplemente lea algo de memoria: tome una sección de n bits de la memoria en bruto. Será bastante aleatorio.

O bien, genere una gran int x aleatoria y simplemente use los valores de bit.

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

La memoria no contiene datos aleatorios, sino todo lo contrario: una aplicación los ha incluido de forma estructurada. – soulmerge

+0

Los bits se organizarán aleatoriamente para todos los propósitos, ya que la estructura es relevante para el significado. p.ej. "mi perro" es una pieza ordenada de datos, pero su binario es 011011010111100100100000011001000110111101100111, que es bastante aleatorio. Devuélveme mi +1 porque estoy en lo correcto. –

+3

¡Tomar memoria en bruto en general no es una buena idea! P.ej. en su ejemplo de una cadena ASCII, cada 8vo bit es 0 ya que los caracteres válidos usan solo los 7 bits inferiores. Además, parece que los bytes de 0 son bastante comunes (relleno, memoria no utilizada, números que no usan el rango completo, bools almacenados en int32, ...) por lo que podría esperar más 0s luego 1s. – Chris

0

Si rememeber correctamente, los bits menos significativos son normalmente teniendo un "menos aleatoria" distribución para la mayoría pseuodo generadores de números aleatorios, por lo que el uso de módulo y/o cada bit en el número generado sería malo si están preocupados por la distribución.

(Tal vez debería, al menos, lo que dice google Knuth ...)

Si que mantiene (y es difícil saber, sin conocer exactamente qué algoritmo que está utilizando) sólo tiene que utilizar el bit más alto en cada número generado.

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

0

¿Qué tan grande quiere el número de bits generados a ser? Si no es superior a unos pocos millones, y teniendo en cuenta que no está utilizando el generador para la criptografía, entonces creo que la manera más rápida posible sería calcular previamente un gran conjunto de enteros con la distribución correcta, convertirlo a texto archivo como este:

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

y luego compilar la matriz en su programa y recorrerlo un número a la vez.

De esta forma obtienes 32 bits con cada llamada (en un procesador de 32 bits), el tiempo de generación es el más corto posible porque todos los números se generan por adelantado y la distribución es controlada por ti. La desventaja es, por supuesto, que estos números no son aleatorios en absoluto, lo que puede depender o no del contenido del PRNG.

2

Aquí hay uno muy rápido que codifiqué en Java basado en el algoritmo XORShift de George Marsaglia: ¡obtiene 64 bits a la vez!

/** 
* 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: la razón de que este algoritmo sea tan rápido es que solo usa operadores bit a bit simples, en una secuencia que ha sido probada (Marsaglia) para generar una secuencia aleatoria de psuedo "lo suficientemente buena". Esto * no * es criptográficamente fuerte, pero es lo suficientemente bueno para juegos, simulaciones, etc. – mikera

0

si sólo se necesita un poco a la vez intenta bool coinToss() { return rand()&1; } sería técnicamente una manera más rápida para generar los bits a causa de la sustitución del 2% con una & 1 que son equivalentes.

Cuestiones relacionadas