2011-02-08 9 views

Respuesta

8

Esto es comúnmente utilizado:

srand (time(NULL)); 

ejecución de todo el código C es determinista, así que hay que traer algo que es diferente cada vez que se llama a la srand. En este caso es el momento.

O puede leer datos del /dev/random (ábralo como cualquier otro archivo).

+3

Si el programa se ejecuta varias veces en un segundo, la misma secuencia de números aleatorios se generarán múltiples veces como se utilizó la misma semilla! – Abhi

+0

si no quiere cambiar nada, puede simplemente dormir (1). Pero será extremadamente lento – Tebe

11

Para generar una secuencia de números pseudorandom, el generador debe ser seeded. La semilla determina completamente la secuencia de números que se producirán. En C, inicia con srand, como lo indica. De acuerdo con la página del manual srand(3), no siembra explícita implica que el generador utilizará 1 como una semilla. Esto expande por qué siempre ves los mismos números (pero recuerda que la secuencia en sí es bastante aleatoria, con calidad según el generador utilizado, aunque la secuencia sea la misma cada vez).

El usuario mzabsky señala que una forma de obtener una semilla que se siente aleatoria para un usuario humano es sembrar con el tiempo. Otro método común (que acabo de ver que mzabsky también señala, lo siento) es sembrar el generador con los contenidos del generador de números aleatorios del sistema, que se basa en un conjunto de entropía alimentado por elementos como el movimiento del mouse, los tiempos del disco, etc. no puede extraer mucha aleatoriedad del generador del sistema, ya que no será capaz de reunir suficiente entropía. Pero si dibujas una semilla de ella, habrás elegido al azar una secuencia de números aleatorios en tu programa. Aquí está un ejemplo de cómo hacerlo en C en Linux:

unsigned int seed; 
FILE* urandom = fopen("/dev/urandom", "r"); 
fread(&seed, sizeof(int), 1, urandom); 
fclose(urandom); 
srand(seed); 

A la luz de la respuesta de Conrad Meyer, que pensé en elaborar un poco más. Yo dividiría el uso de números aleatorios en tres categorías:

  1. Variación. Si usa números aleatorios para crear un comportamiento aparentemente aleatorio o variado en, por ejemplo, un juego, no necesita pensar mucho sobre el tema o sobre elegir una semilla adecuada. Siembre con el tiempo y mire otra solución si resulta que no es lo suficientemente buena. Incluso los RNG relativamente malos se verán lo suficientemente aleatorios en este escenario.
  2. Simulaciones científicas. Si usa números aleatorios para trabajos científicos, como los cálculos de Monte Carlo, debe tener cuidado de elegir un generador bueno. Su semilla debe ser reparado (o modificable por el usuario). Usted no desea variación (en el sentido anterior); quieres un comportamiento determinista pero una buena aleatoriedad.
  3. Criptografía. Querrá ser extremadamente cuidadoso. Esto probablemente esté fuera del alcance de este hilo.
3

Tenga cuidado; la página de manual rand(3) en Linux señala que las implementaciones rand() en algunas plataformas no dan una buena aleatoriedad en los bits de orden inferior. Por esta razón, es posible que desee utilizar una biblioteca para adquirir números aleatorios reales. Glib proporciona funciones útiles como g_random_int_range() que pueden adaptarse mejor a su propósito.

4

Si está utilizando un sistema operativo que no proporciona/dev/random a continuación, utilizar algo así como lo que se muestra a continuación

timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec * t1.tv_sec);

Esta pieza de código puede ser fácilmente portado a otros sistemas operativos.

Para mejorar la semilla, puede combinar (tal vez utilizando MD5 o un algoritmo de suma de control) el producto de tiempo que se muestra arriba con una dirección MAC de la máquina host.

timeval t1;
gettimeofday(&t1, NULL);
unsigned int seed = t1.tv_usec * t1.tv_sec;

unsigned char mac_addr[6];
getMAC(&mac_addr);
improveSeedWithMAC(&seed, mac_addr) ; // MD5 or checksum ...

srand(seed);