Me gustaría complementar las excelentes respuestas de Angry Shoe y peterchen con una breve descripción del estado del arte en 2015:
Algunas buenas elecciones
randutils
La randutils
biblioteca (presentación) es una novedad interesante, que ofrece una interfaz simple y capacidades aleatorias robustas (declaradas). Tiene las desventajas de que agrega dependencia a su proyecto y, al ser nuevo, no se ha probado exhaustivamente. De todos modos, al ser gratis (licencia MIT) y solo de encabezado, creo que vale la pena intentarlo.
Muestra mínima: una tirada de dado
#include <iostream>
#include "randutils.hpp"
int main() {
randutils::mt19937_rng rng;
std::cout << rng.uniform(1,6) << "\n";
}
Incluso si uno no está interesado en la biblioteca, el sitio web ( http://www.pcg-random.org/ ) proporciona muchos artículos interesantes sobre el tema de la generación de números aleatorios en general y la biblioteca C ++ en particular.
Boost.Random
Boost.Random
(documentación) es la biblioteca que inspiró C++11
's <random>
, con el que comparte gran parte de la interfaz. Si bien teóricamente también es una dependencia externa, Boost
ahora tiene el estado de biblioteca "cuasi estándar", y su Random
módulo podría considerarse como la opción clásica para la generación de números aleatorios de buena calidad. Presenta dos ventajas con respecto a la C++11
solución:
- es más portátil, solo necesita compatibilidad con el compilador para C ++ 03
- sus
random_device
métodos de usos específicos del sistema a la oferta de siembra de buena calidad
El único pequeño defecto es que la oferta del módulo random_device
no es solo de encabezado, hay que compilar y vincular boost_random
.
Muestra mínima: una tirada de dado
#include <iostream>
#include <boost/random.hpp>
#include <boost/nondet_random.hpp>
int main() {
boost::random::random_device rand_dev;
boost::random::mt19937 generator(rand_dev());
boost::random::uniform_int_distribution<> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Si bien la muestra mínima funciona bien, los programas reales deberían usar un par de mejoras:
- hacer
mt19937
a thread_local
: el generador es bastante voluminoso (> 2 KB) y es mejor que no se asigne en la pila
- semilla
mt19937
con más de un entero: el Mersenne Twister tiene un estado grande y puede beneficiarse de más entropía durante la inicialización
Algunas opciones no tan buenas
La biblioteca C ++ 11
Si bien es la solución más idiomática, la <random>
biblioteca no ofrece mucho a cambio de la complejidad de su interfaz incluso para las necesidades básicas. La falla está en std::random_device
: el Estándar no exige una calidad mínima para su salida (siempre que entropy()
devuelva 0
) y, a partir de 2015, MinGW (no es el compilador más utilizado, pero no es una opción esotérica) siempre imprimirá 4
en la muestra mínima.
Muestra mínima: una tirada de dado
#include <iostream>
#include <random>
int main() {
std::random_device rand_dev;
std::mt19937 generator(rand_dev());
std::uniform_int_distribution<int> distr(1, 6);
std::cout << distr(generator) << '\n';
}
Si la implementación no está podrida, esta solución debería ser equivalente a la de Boost, y se aplican las mismas sugerencias.
La solución de Godot
Muestra mínima: una tirada de dado
#include <iostream>
#include <random>
int main() {
std::cout << std::randint(1,6);
}
Esta es una solución simple, efectiva y ordenada. Solo es un defecto, llevará un tiempo compilarlo, aproximadamente dos años, siempre que C ++ 17 se publique a tiempo y la randint
función experimental esté aprobada en el nuevo estándar. Quizás en ese momento también mejoren las garantías sobre la calidad de la siembra.
Muestra mínima: una tirada de dado
#include <cstdlib>
#include <ctime>
#include <iostream>
int main() {
std::srand(std::time(nullptr));
std::cout << (std::rand() % 6 + 1);
}
La antigua solución C se considera dañina y por buenas razones (consulte las otras respuestas aquí o este análisis detallado ). Aún así, tiene sus ventajas: es simple, portátil, rápido y honesto, en el sentido de que se sabe que los números aleatorios que se obtienen son poco decentes y, por lo tanto, no se tiene la tentación de usarlos para propósitos serios.
La solución de trol de contabilidad
Muestra mínima: una tirada de dado
#include <iostream>
int main() {
std::cout << 9; // http://dilbert.com/strip/2001-10-25
}
Si bien 9 es un resultado algo inusual para una tirada de dado normal, uno tiene que admirar la excelente combinación de buenas cualidades en esta solución, que logra ser la más rápida, simple, más fácil de usar y más portátil. Sustituyendo 9 con 4, se obtiene un generador perfecto para cualquier tipo de Dungeons and Dragons dado, mientras se evitan los valores cargados de símbolos 1, 2 y 3. El único pequeño defecto es que, debido al mal genio de los trolls contables de Dilbert, este programa en realidad genera un comportamiento indefinido.