2012-02-27 11 views
22

Cada vez que ejecuto un programa con rand() me da los mismos resultados.¿Por qué rand() produce la misma secuencia de números en cada ejecución?

Ejemplo:

#include <iostream> 
#include <cstdlib> 

using namespace std; 

int random (int low, int high) { 
    if (low > high) return high; 
    return low + (rand() % (high - low + 1)); 
} 
int main (int argc, char* argv []) { 
    for (int i = 0; i < 5; i++) cout << random (2, 5) << endl; 
} 

Salida:

3 
5 
4 
2 
3 

Cada vez que ejecute el programa se emite los mismos números cada vez. ¿Hay alguna forma de evitar esto?

Respuesta

33

La semilla para el generador de números aleatorios no está configurada.

Si se llama a srand (time (NULL)) por lo que recibirá los resultados más aleatorios:

La razón es que un número aleatorio generado por la función rand() no es realmente aleatoria. Simplemente es una transformación.Wikipedia ofrece una mejor explicación del significado del generador de números pseudoaleatorios: generador determinístico de bits aleatorios. Cada vez que llamas a rand() toma la semilla y/o los últimos números aleatorios generados (el estándar C no especifica el algoritmo utilizado, aunque C++ 11 tiene facilidades para especificar algunos algoritmos populares), ejecuta un operación matemática en esos números, y devuelve el resultado. Entonces, si el estado de la semilla es el mismo cada vez (como lo es si no llamas a srand con un número verdaderamente aleatorio), siempre obtendrás los mismos números 'aleatorios'.

Si usted quiere saber más, se puede leer lo siguiente:

http://www.dreamincode.net/forums/topic/24225-random-number-generation-102/

http://www.dreamincode.net/forums/topic/29294-making-pseudo-random-number-generators-more-random/

1

Debe inicializar el generador de números aleatorios (consulte la función 'srand'). Suponiendo que no está haciendo criptografía, entonces sembrarlo con la salida de 'tiempo' es probablemente lo suficientemente bueno.

11

Si llama al rand() sin llamar primero al srand(), actuará como si hubiera llamado srand(1) implícitamente. El bit correspondiente de la norma C99 7.20.2.2 The srand function (sobre la que se basa cstdlib) afirma:

Si rand se llama antes se han hecho llamadas a srand, la misma secuencia se genera como cuando srand se llama en primer lugar con una semilla valor de 1.

En otras palabras, usted será obtener la misma secuencia cada vez. Puede cambiar su main en:

int main (int argc, char* argv []) { 
    srand (time (0)); // needs ctime header. 
    for (int i = 0; i < 5; i++) 
     cout << random (2, 5) << endl; 
    wait(); 
} 

de solucionar este problema, suponiendo que no se ejecutan más de una vez por segundo.

Como se mencionó, necesitará el encabezado ctime para esto. También debe extraer en cstdlib ya que es donde viven rand y srand. También suele ser una buena idea usar los encabezados cXXX en lugar de los XXX.h (cmath en lugar de math.h, por ejemplo).

Así, después de haber hecho todas las esos cambios (y el uso de espacios de nombres explícitos, que yo prefiero, aunque otros no pueden), que iba a terminar con:

#include <iostream> 
#include <cstdlib> 
#include <ctime> 
#include <cmath> 

void wait() { 
    int e; 
    std::cin >> e; 
} 

int random (int low, int high) { 
    if (low > high) return high; 
    return low + (std::rand() % (high - low + 1)); 
} 

int main (int argc, char* argv []) { 
    std::srand (std::time (0)); 
    for (int i = 0; i < 5; i++) 
     std::cout << random (2, 5) << '\n'; 
    wait(); 
} 

que da una secuencia diferente cada vez que lo ejecutarlo, por algunas veces de todos modos. Obviamente, hay un límite estricto sobre cuándo se repetirán los datos (solo hay 4 posibilidades) y la naturaleza "aleatoria" de la salida significa que también puede repetirse antes de esa fecha :-)

0

En realidad está recibiendo números aleatorios psuedo. Para hacerlos "más aleatorios", puedes sembrar el generador de números aleatorios usando algo que "cambie" (más comúnmente la hora actual).

+1

Nit: Matemáticamente, eso no los hará "más aleatorios". –

+0

Es cierto, pero en el contexto de la pregunta del OP ... (más está entre comillas ;-) – John3136

2

Esa es una característica de la función rand().

Lo que tiene no es un generador de números aleatorios, sino más estrictamente un "Pseudo Random Number Generator". Ser capaz de reproducir las mismas secuencias aleatorias para la misma semilla (semilla utilizando la función srand(x)) puede ser importante para reproducir errores o para preservar el estado en las ejecuciones del programa.

Personalmente, uso esta característica para poder pausar/persistir los procesos de representación en un renderizador de terreno basado en monte carlo. Un buen efecto secundario es que puede garantizar diferentes experimentos de monte carlo en diferentes máquinas y, por lo tanto, generar resultados garantizados diferentes que luego se pueden reducir en un paso final a un resultado final de mayor calidad (por supuesto, puede reutilizarlo más adelante). este resultado final de mayor calidad para producir resultados de mayor calidad).

Tenga en cuenta, sin embargo, que ni C ni C++ definen la secuencia de números desde rand(). Entonces, si necesita secuencias garantizadas en todas las plataformas, utilice uno de los nuevos generadores de números aleatorios de C++ 11 (por ejemplo, mersenne twister), haga lo suyo (sin embargo, algunos generadores son casi triviales porque la mayoría confía en un comportamiento de desbordamiento específico). la implementación puede no ser trivial), o usar un componente de un tercero (ej. boost :: random).

1

use randomize(). Genera automáticamente el valor. O si desea usar rand(), puede sembrar utilizando srand (seedvalue); el valor de la semilla puede ser similar al tiempo del sistema ... eso le dará diferentes números aleatorios cada vez

+1

'randomize' no es una función estándar de C++. ¿De qué plataforma estás hablando? –

Cuestiones relacionadas