Números aleatorios en C ++

12

Recientemente me acostumbré a los idiomas modernos que incluyen un buen generador aleatorio, que generalmente es el Mersenne Twister; ahora que volví a C ++ tengo que decidir qué usar.

Busqué implementaciones de Mersenne Twister y noté que hay muchas: ¿hay alguna que sea más utilizada y generalizada, o se supone que debo elegir una, suponiendo que todas sean igualmente buenas?

o0 '.
fuente
1
Me gusta su separación de C ++ y los lenguajes modernos.
jcora
2
Tal vez decir "nivel superior" era más apropiado.
o0 '.
Creo que esta pregunta pertenece a stackoverflow
TravisG
55
En SO, daría una respuesta diferente porque no sabría que era para un motor de juego en lugar de, por ejemplo, simulaciones de Monte Carlo para terapias médicas, en cuyo caso no tener 624 dimensiones de aleatoriedad puede ser mortal.

Respuestas:

19

C ++ 11 incluye un generador Mersenne Twister de forma predeterminada como parte de su nueva <random>interfaz. Por ejemplo, para generar enteros de manera uniforme entre [-10, 10] utilizando MT:

std::mt19937 eng; // This is the Mersenne Twister
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

La mayor parte de esto también está disponible en cualquier compilador que ofrezca TR1, aunque los nombres son ligeramente diferentes; std::tr1::mt19937y std::tr1::uniform_int<int>.

Usualmente advierto a las personas que no usen Mersenne Twister. Es un algoritmo aceptable, pero gran parte de su popularidad es solo marketing. 624 dimensiones de aleatoriedad son más de lo que la mayoría de las personas necesitan, y el MT conlleva requisitos de estado relativamente pesados ​​y, cuando realiza un recuento completo de la tabla, puede volar el caché. Personalmente, soy partidario de xorshift, que proporciona períodos excelentes y distribuciones razonables para todo lo que un juego necesita, con muy poca memoria y requisitos de CPU.

He escrito un generador xorshift compatible con C ++ 11 (¿en su mayoría?) - xorshift.hpp , xorshift.cpp - y lo coloqué en el dominio público. Puede conectar esto a cualquier función de aleatorización de C ++ 11, como se indica arriba:

xorshift eng;
std:::uniform_int_distribution<int> dist(-10, 10)
for (int i = 0; i < 10; ++i)
    std::cout << dist(eng) << std::endl;

fuente
55
Sí, ese es el tipo de respuesta que estaba buscando, por eso publiqué aquí en gamedev:)
o0 '.
1
Solo quería señalar que nada en los archivos que vinculó indica que están en el dominio público. La forma en que funciona la ley de derechos de autor, realmente debe haber una nota clara al respecto, ya que la ley asume "todos los derechos reservados" por defecto. En realidad, es incluso más seguro usar algo como la licencia MIT o BSD de 2 cláusulas, ya que algunas jurisdicciones básicamente no reconocen que "esto es de dominio público" como legalmente vinculante. Si está interesado en ver a las personas usar su código, puede valer la pena ocuparse de eso.
Sean Middleditch
1
@seanmiddleditch: estoy siendo claro al respecto aquí mismo. Si lo desea bajo una licencia de estilo MIT, seguiré el ejemplo de SQLite y se lo daré por solo $ 1000.
La falta si un encabezado en el código que declara algo (que SQLite hace, iirc) es el problema principal. Si no te importa, eso es genial. Solo te estaba dando una sugerencia amigable.
Sean Middleditch
1

Otro RNG que he usado antes para propósitos de gamedev es el "pequeño" RNG de Bob Jenkins, descrito aquí .

(También tiene un RNG de fuerza criptográfica llamado ISAAC, pero es más grande y más lento, y los juegos no necesitan ese nivel de fuerza).

Nathan Reed
fuente
1
Parece más costoso que xorshift (4 xors y 3 turnos vs. 4 sumas, 6 turnos, 2 ors y un xor), tiene un período peor y corre el riesgo de ciclos muy cortos con ciertas inicializaciones. Se ve rápido pero no más rápido; período bueno pero nada cerca de lo óptimo; mismas cualidades básicas de distribución que xorshift; No veo ninguna razón para usarlo.
Lo suficientemente justo. No sé lo suficiente sobre el análisis RNG para profundizar en las propiedades de distribución y ciclo.
Nathan Reed