Como sugiere el título, estoy tratando de encontrar una manera de generar números aleatorios usando la nueva <random>
biblioteca C ++ 11 . Lo he intentado con este código:
std::default_random_engine generator;
std::uniform_real_distribution<double> uniform_distance(1, 10.001);
El problema con el código que tengo es que cada vez que lo compilo y lo ejecuto, siempre genera los mismos números. Entonces, mi pregunta es ¿qué otras funciones en la biblioteca aleatoria pueden lograr esto mientras son verdaderamente aleatorios?
Para mi caso de uso particular, estaba tratando de obtener un valor dentro del rango [1, 10]
std::mt19937
como motor a menos que tenga una buena razón para no hacerlo. Y la distribución es un intervalo cerrado en ambos extremos.std::uniform_int_distribution
, que está cerrado en ambos extremos.Respuestas:
Stephan T. Lavavej (stl) de Microsoft hizo una charla en Going Native sobre cómo usar las nuevas funciones aleatorias de C ++ 11 y por qué no usarlas
rand()
. En él, incluyó una diapositiva que básicamente resuelve su pregunta. Copié el código de esa diapositiva a continuación.Puedes ver su charla completa aquí: http://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful
Usamos
random_device
una vez para sembrar el generador de números aleatorios llamadomt
.random_device()
es más lento quemt19937
, pero no necesita ser sembrado porque solicita datos aleatorios de su sistema operativo (que procederá de varias ubicaciones, como RdRand, por ejemplo).Al mirar esta pregunta / respuesta , parece que
uniform_real_distribution
devuelve un número en el rango[a, b)
, donde lo desee[a, b]
. Para hacer eso, enuniform_real_distibution
realidad debería verse así:fuente
default_random_engine
, de acuerdo con el manual de c ++, es la que la implementación ha considerado más útildefault_random_engine
exista.std::default_container
, con suerte no hay las personas que se consideran programadores que no conocen las diferencias, muchos lenguajes de secuencias de comandos tienen una estructura de tipo de mapa predeterminada, que podría implementarse en una variedad de formas que el usuario puede no conocernextafter
llamada es exagerada para la mayoría de las aplicaciones. Las posibilidades de undouble
aterrizaje aleatorio exactamente en el punto final son tan minúsculas que no hay una diferencia práctica entre incluirlo y excluirlo.std::vector
analogía no funciona aquí porque en realidadstd::vector
es un buen valor predeterminado debido al almacenamiento en caché de la CPU. Incluso tiene un rendimiento superiorstd::list
para la inserción en el medio. Eso es cierto incluso si comprende todos los contenedores y podría tomar una decisión informada basada en la complejidad algorítmica.Mi biblioteca 'aleatoria' proporciona un contenedor altamente conveniente alrededor de las clases aleatorias de C ++ 11. Puedes hacer casi todas las cosas con un simple método 'get'.
Ejemplos:
Número aleatorio en un rango
Booleano aleatorio
Valor aleatorio de un std :: initilizer_list
Iterador aleatorio del rango de iterador o todos los contenedores
¡Y aún más cosas! Echa un vistazo a la página de github:
https://github.com/effolkronium/random
fuente
Remarqué todas las cosas anteriores, otras 40 páginas con c ++ como esta y vi el video de Stephan T. Lavavej "STL" y todavía no estaba seguro de cómo funcionan los números aleatorios en la praxis, así que me tomé un domingo completo para descubrir de qué se trata y cómo funciona y se puede utilizar.
En mi opinión, STL tiene razón sobre "no usar srand nunca más" y lo explicó bien en el video 2 . También recomienda usar:
a)
void random_device_uniform()
- para la generación encriptada pero más lenta (de mi ejemplo)b) los ejemplos con
mt19937
- más rápido, capacidad de crear semillas, no encriptadoSaqué todos los libros de c ++ 11 reclamados a los que tengo acceso y encontré que los autores alemanes como Breymann (2015) todavía usan un clon de
solo con en
<random>
lugar de<time> and <cstdlib>
#incluidos, así que tenga cuidado de aprender solo de un libro :).Significado: eso no debería usarse desde c ++ 11 porque:
Finalmente encontré la mejor explicación de 20 libros en los más nuevos de Bjarne Stroustrups, y él debería saber sus cosas, en "Un recorrido por C ++ 2019", "Principios y práctica de programación usando C ++ 2016" y "El lenguaje de programación C ++ 4ta edición 2014 "y también algunos ejemplos en" Lippmans C ++ primer quinta edición 2012 ":
Y es realmente simple porque un generador de números aleatorios consta de dos partes: (1) un motor que produce una secuencia de valores aleatorios o pseudoaleatorios. (2) una distribución que mapea esos valores en una distribución matemática en un rango.
A pesar de la opinión del chico de Microsofts STL, Bjarne Stroustrups escribe:
El
void die_roll()
ejemplo es de Bjarne Stroustrups: buena idea para generar motor y distribución conusing
(más sobre eso aquí) .Para poder hacer un uso práctico de los generadores de números aleatorios proporcionados por la biblioteca estándar
<random>
aquí, algunos códigos ejecutables con diferentes ejemplos se reducen a los menos necesarios que con suerte ahorren tiempo y dinero para ustedes:Creo que eso lo suma todo y, como dije, me tomó un montón de lectura y tiempo para destilarlo a esos ejemplos; si tiene más información sobre la generación de números, me alegra escuchar eso a través de la tarde o en la sección de comentarios y lo agregará si es necesario o editará esta publicación. Bool
fuente
Aquí hay algo que acabo de escribir en ese sentido:
~
fuente
Aquí hay algunos recursos que puede leer sobre el generador de números pseudoaleatorios.
https://en.wikipedia.org/wiki/Pseudorandom_number_generator
Básicamente, los números aleatorios en la computadora necesitan una semilla (este número puede ser la hora actual del sistema).
Reemplazar
Por
fuente
Tienes dos situaciones comunes. La primera es que desea números aleatorios y no está demasiado preocupado por la calidad o la velocidad de ejecución. En ese caso, use la siguiente macro
eso le da p en el rango de 0 a 1 - epsilon (a menos que RAND_MAX sea más grande que la precisión de un doble, pero preocúpese por eso cuando lo haga).
int x = (int) (uniforme () * N);
Ahora da un entero aleatorio en 0 a N -1.
Si necesita otras distribuciones, debe transformar p. O a veces es más fácil llamar a uniform () varias veces.
Si desea un comportamiento repetible, siembre con una constante, de lo contrario siembre con un llamado al tiempo ().
Ahora, si le preocupa la calidad o el rendimiento del tiempo de ejecución, vuelva a escribir uniform (). Pero de lo contrario no toque el código. Mantenga siempre uniform () en 0 a 1 menos épsilon. Ahora puede ajustar la biblioteca de números aleatorios de C ++ para crear un mejor uniforme (), pero esa es una especie de opción de nivel medio. Si le preocupan las características del RNG, entonces también vale la pena invertir un poco de tiempo para comprender cómo funcionan los métodos subyacentes, luego proporcione uno. Por lo tanto, tiene el control completo del código y puede garantizar que con la misma semilla, la secuencia siempre será exactamente la misma, independientemente de la plataforma o la versión de C ++ a la que se vincule.
fuente