¿Hay alguna razón para no usar el generador de números aleatorios estándar de C ++?

C ++ tiene:

  • 3 plantillas de motor de números pseudoaleatorios: std :: linear_congruential_engine, std :: mersenne_twister_engine y std :: subtract_with_carry_engine
  • 3 plantillas de adaptador std :: discard_block_engine, std :: independent_bits_engine y std :: shuffle_order_engine
  • 9 motores de números pseudoaleatorios concretos: std :: minstd_rand0, std :: minstd_rand, std :: mt19937, std :: mt19937_64, std :: ranlux24_base, std :: ranlux48_base, std :: ranlux24, std :: ranlux48 y std :: knuth_b.
  • 1 motor de números aleatorios no determinista (respaldado por hardware), std :: random_device.
  • 21 distribuciones de números aleatorios que pueden funcionar con esos motores para producir números aleatorios distribuidos de la forma que desee

Parece que a la mayoría de la gente le gusta std :: mt19937 (el Mersenne Twister de 32 bits), aunque es un poco exagerado para muchos trabajos.

Ver cppreference: generación de números pseudoaleatorios

La razón para no usar un generador o distribución de números aleatorios estándar de C ++ es cuando estás haciendo un trabajo estadístico o criptográfico que realmente requiere un motor diferente. Por ejemplo, boost.random ofrece bastantes motores y distribuciones adicionales, consulte Referencia – 1.60.0

También hay una pequeña advertencia de que, aunque los motores son 100% deterministas y portátiles, las distribuciones no lo son; solo están obligados a satisfacer la función de distribución de probabilidad, no a proporcionar exactamente los mismos números para la misma semilla / motor. Cuando se necesitan distribuciones portátiles, boost.random también ayuda.

Por “generador de números aleatorios estándar”, supongo que te refieres a std::default_random_engine . Hay bastantes razones para evitar usarlo para cualquier aplicación remotamente seria:

  • El algoritmo PRNG que este generador emplea específicamente depende de la implementación de la biblioteca, lo que significa que no tiene idea de la calidad estadística del generador.
  • Otra consecuencia de lo anterior es que no puede esperar reproducibilidad: el uso de la misma semilla en diferentes sistemas podría no producir la misma serie de valores pseudoaleatorios.
  • Además, la mayoría de las bibliotecas implementarán este motor como una definición de tipo de std::linear_congruential_engine o std::subtract_with_carry_engine , que ambas funcionan estadísticamente bastante mal.

Sin embargo, desafortunadamente, la historia no termina ahí. Actualmente (C ++ 11/14), la facilidad estándar de números aleatorios ( ) está prácticamente rota de muchas maneras, lo que la hace inútil para aplicaciones serias. Si tiene curiosidad, puede leer más sobre esto aquí y aquí, pero eso está más allá del alcance de esta pregunta, creo.

Como dice en la respuesta de Sergey Zubkov, ¡incluso “listo para usar” tiene muchas opciones!

Pero puedo pensar en dos casos más en los que es posible que no desee ninguno de ellos: criptografía y videojuegos.

  1. Ni RANLUX ni Mersenne Twister son crypto-PRNG (sin embargo, son lo suficientemente buenos para el software de estadísticas). Prefiero encontrar alguna biblioteca de criptografía y usar lo que venga con ella (suponiendo que sea una biblioteca popular, endurecida por la batalla).
  2. Para los videojuegos, incluso la aleatoriedad de muy baja calidad podría ser lo suficientemente buena, siempre que sea realmente rápida, como xorshift. O tal vez incluso sin PRNG en absoluto; Incluso algunas funciones muy simples pueden parecer aleatorias para un humano en algunos casos (los humanos apestan al azar).