C ++ Predictable Rand () Salida

Después de notar que la función rand () producía la misma salida de 41 cada vez, sembré el generador usando srand (tiempo (0)). Eso solucionó el problema de la salida recurrente, pero ahora me está dando números cada vez mayores. (IE 245, 248, 250, 253, 255, 256). Puedo entender que está aumentando debido a la influencia de la hora del sistema, pero ¿es esto normal?

Aquí está mi progtwig:

#include  #include  #include  using namespace std; int main() { int number; srand(time(0)); cout << rand() % 1000; return 0; } 

Estoy ejecutando esto repetidamente y no en un bucle. Resultados de pruebas múltiples: 285 295 305 311 325 334 344 354 355

C ++ rand() de MS utiliza el generador aleatorio más simple generador lineal congruente

Este es el código para ello:

 int __cdecl rand ( void ) { _ptiddata ptd = _getptd(); return( ((ptd->_holdrand = ptd->_holdrand * 214013L + 2531011L) >> 16) & 0x7fff ); } 

Por lo tanto, cuando ejecuta su función, simplemente establece el primer valor (que obviamente aumenta solo algunas unidades de vez en cuando si ejecuta su progtwig rápidamente)

Ahora, si inserta su ecuación matemática del rand() un valor x+a donde x es el valor con el que se llamó a su función la última vez y a es la variación de su tiempo desde esa llamada que notará: ((x + a) * 214013 + 2531011) >> 16 = (x * 214013 + 2531011 + a * 214013) >> 16

Ya que ejecutas tu progtwig muy rápido. Su a varía entre 0 y 5 segundos, digamos. Luego, su a*214013 tiene un valor máximo de 1070065 ahora, cuando se desplaza a la derecha este número en 16 bits, se a*214013 un decimal de 16 y esto es aproximadamente la diferencia entre su nueva salida y la anterior (digo aproximadamente porque no puede diga que (x * 214013 + 2531011 + a * 214013) >> 16 = (x * 214013 + 2531011 >> 16) + (a * 214013 >> 16) debido a los acarreos)

Este error aparece aproximadamente una vez a la semana aquí:

Si llamas a srand() cada vez que llamas a rand (), entonces no obtienes números aleatorios en absoluto, obtienes una función hash de la hora. Llame a srand() UNA VEZ, Y SOLAMENTE UNA VEZ, fuera del bucle, preferiblemente al comienzo de su progtwig, luego llame a rand() tantas veces como sea necesario para obtener los valores.

No hay tal cosa como generar “un número aleatorio”. Si necesita números aleatorios sobre una serie de invocaciones de progtwigs, no tiene más remedio que generar esos números aleatorios fuera del progtwig. Una forma de hacerlo es leer desde /dev/urandom (en Linux) o usar CryptGenRandom (en Windows). Otra opción es usar hardware, o un servicio como random.org .

No importa qué tan bueno sea el generador que tenga: si realiza un pedido de cada llamada, no obtendrá números aleatorios, obtendrá una función hash del valor de inicio. Si su valor inicial cambia lo suficientemente rápido, y la función hash es muy buena, podría ser lo suficientemente buena, pero aún no está usando el algoritmo RNG en absoluto.

No tengo idea de por qué está obteniendo esos resultados, pero hay mejores formas en C ++ 11:

 #include  #include  int main() { auto rnd = std::default_random_engine(std::random_device{}()); std::uniform_int_distribution<> dis(1, 999); std::cout << dis(rnd) << '\n'; } 

rand se implementa como un generador lineal congruente en las bibliotecas de tiempo de ejecución y esto tiene la forma:

 result = (seed * result + offset) % big_number 

Si consideramos que big_number es infinito y ejecuta su progtwig en el momento t que obtiene

 result = t * result + offset 

Si ejecutas el progtwig nuevamente después de un período muy corto, obtienes

 result = (t + alpha)* result + offset 

Si la biblioteca de tiempo de ejecución inicializa el resultado con un valor pequeño, el resultado mostrado boostá con el valor pequeño del alpha * result .

Reemplazar el time() con un contador de mayor resolución mejoraría enormemente esto. Por ejemplo, en x86, la instrucción rdtcs (a menudo disponible como comstackdor intrínseco) casi resolvería el problema.

Una mejor solución es usar un generador congruente no lineal para sembrar rand() como el sugerido por Jesse Good, que también está disponible en el comstackdor que no es c ++ 11 a través de la biblioteca boost.

Cuando sea posible, es mejor atenerse a los generadores aleatorios c ++ 11 en lugar de a c rand.

La forma en que funciona rand es que necesitas seguir dos reglas:

  1. primero debes srand ( srand ) y
  2. no quieres sembrarlo antes de cada llamada a rand . Solo debes sembrarlo una vez antes de toda tu secuencia.

Así que para probarlo realmente, su código debería verse más como esto:

 int main() { srand(time(0)); // Output a sequence of 100 random numbers, each less than 1000 for ( int i = 0; i < 100; i++ ) cout << rand() % 1000 << endl; return 0; } 

Si el progtwig por necesidad solo genera un número aleatorio en cada ejecución y el progtwig se ejecuta una vez por segundo o más, entonces el time(0) puede no ser una semilla adecuada. Quizás utilizando clock_gettime(3) que le dará algo más en milisegundos.

Recientemente me encontré con el mismo problema y descubrí que el comentario de Karoly Horvath sobre tu pregunta original resolvió el problema, aunque es un poco “intrépido”. Estaba viendo un aumento predecible en los valores de retorno, y después de pegar otro rand() inmediatamente después del srand() , el problema desapareció. Terminé con esto:

 srand(time(NULL)); rand(); int seed = rand(); 

Me gustaría averiguar por qué sucede esto … pero mientras tanto, esto funciona.