Suponga que desea utilizar las <random>instalaciones de C ++ en un programa práctico (para alguna definición de "práctico", las restricciones aquí son parte de esta pregunta). Tienes un código más o menos así:
int main(int argc, char **argv) {
int seed = get_user_provided_seed_value(argc, argv);
if (seed == 0) seed = std::random_device()();
ENGINE g(seed); // TODO: proper seeding?
go_on_and_use(g);
}
Mi pregunta es, ¿para qué tipo debes usar ENGINE?
Solía decir siempre
std::mt19937porque era rápido escribir y tenía reconocimiento de nombre. Pero en estos días parece que todos dicen que el Mersenne Twister es muy pesado y poco amigable con el caché y ni siquiera pasa todas las pruebas estadísticas que otros hacen.Me gustaría decirlo
std::default_random_engineporque es el obvio "defecto". Pero no sé si varía de una plataforma a otra, y no sé si estadísticamente es bueno.Dado que todos están en una plataforma de 64 bits en estos días, ¿al menos deberíamos usar
std::mt19937_64másstd::mt19937?Me gustaría decir
pcg64oxoroshiro128porque parecen respetados y ligeros, pero no existen en<random>absoluto.No sé nada acerca de
minstd_rand,minstd_rand0,ranlux24,knuth_b, etc - sin duda que debe ser bueno para algo?
Obviamente, hay algunas restricciones en competencia aquí.
Resistencia del motor. (
<random>no tiene PRNG criptográficamente fuertes, pero aún así, algunos de los estandarizados son "más débiles" que otros, ¿verdad?)sizeofel motor.Velocidad de su
operator().Facilidad de siembra.
mt19937es notoriamente difícil de sembrar adecuadamente porque tiene mucho estado para inicializar.Portabilidad entre vendedores de bibliotecas. Si un proveedor
foo_engineproduce números diferentes de los de otro proveedorfoo_engine, eso no es bueno para algunas aplicaciones. (Espero que esto no descarte nada excepto tal vezdefault_random_engine).
Sopesando todas estas restricciones lo mejor que pueda, ¿cuál diría que es la respuesta definitiva de "mejor práctica para mantenerse dentro de la biblioteca estándar"? ¿Debo seguir usando std::mt19937o qué?

Respuestas:
C ++ Reference enumera todos los motores aleatorios actualmente proporcionados por C ++. Sin embargo, la selección de motores deja mucho que desear (por ejemplo, vea mi lista de generadores aleatorios de alta calidad ). Por ejemplo:
default_random_engineestá definida por la implementación, por lo que se desconoce si el motor tiene fallas estadísticas que puedan interesarle a la aplicación.linear_congruential_engineimplementa generadores lineales congruentes. Sin embargo, tienden a tener mala calidad a menos que el módulo sea primo y muy grande (al menos 64 bits). Además, no pueden admitir más semillas que su módulo.minstd_rand0yminstd_randadmitir solo alrededor de 2 ^ 31 semillas.knuth_benvuelve aminstd_rand0y hace una mezcla de Bays-Durham.mt19937ymt19937_64podría admitir muchas más semillas si se inicializaran mejor (por ejemplo, inicializando astd::seed_seqcon múltiples salidas derandom_device, no solo una), pero usan aproximadamente 2500 bytes de estado.ranlux24yranlux48usan aproximadamente 577 bits de estado, pero son lentos (funcionan manteniendo algunos y descartando otras salidas pseudoaleatorias).Sin embargo, C ++ también tiene dos motores que envuelven otro motor para mejorar potencialmente sus propiedades de aleatoriedad:
discard_block_enginedescarta algunas de las salidas de un motor aleatorio dado.shuffle_order_engineimplementa una mezcla aleatoria de Bays-Durham de un motor aleatorio dado.Por ejemplo, es posible, por ejemplo, tener un shuffle de Bays-Durham de
mt19937,ranlux24o una costumbrelinear_congruential_engineconshuffle_order_engine. Quizás el motor envuelto sea de mejor calidad que el original. Sin embargo, es difícil predecir la calidad estadística del nuevo motor sin probarlo .Por lo tanto, en espera de tales pruebas, parece que
mt19937es el motor más práctico en el estándar C ++ por ahora. Sin embargo, soy consciente de al menos una propuesta para agregar otro motor de números aleatorios a futuras versiones de C ++ (consulte el documento C ++ P2075 ).fuente
Según C ++ de referencia ,
default_random_engine:Entonces, para un uso liviano , no necesita preocuparse por nada, sembrar
default_random_engineconEpoch Time (time(0))y eso sería lo suficientemente bueno;)fuente