Librería estándar de C++ <random>
En la librería estándar de C++,<random>el archivo de encabezado proporciona un conjunto de herramientas para generar números aleatorios, cubriendo desde distribuciones uniformes simples hasta distribuciones discretas complejas, ofreciendo una amplia selección para aplicaciones que necesitan números aleatorios. Estas herramientas son muy útiles en campos como simulación, desarrollo de juegos, algoritmos de cifrado, etc.
<random>No solo admite la generación de números pseudoaleatorios, sino también el control de semillas, varias distribuciones de probabilidad, etc., lo que permite a los desarrolladores generar de manera flexible secuencias de números aleatorios que cumplan con requisitos específicos.
<random>La librería se compone de los siguientes tres componentes principales:
- Motor de números aleatorios: el núcleo que genera números pseudoaleatorios, utilizado para controlar la repetibilidad y la aleatoriedad del proceso de generación.
- Distribución de números aleatorios: controla el tipo de distribución de probabilidad que siguen los valores generados.
- Adaptador de números aleatorios: permite ajustar el comportamiento del motor, como
discard_blockadaptadores, etc.
En C++, los generadores de números aleatorios (Random Number Generator, RNG) se pueden dividir en dos categorías principales:
- Generador de números pseudoaleatorios: utilizan algoritmos deterministas para generar secuencias numéricas que parecen aleatorias. Estas secuencias son teóricamente predecibles, pero generalmente son lo suficientemente aleatorias para la mayoría de las aplicaciones.
- Generador de números verdaderamente aleatorios: se basan en procesos físicos (como ruido térmico, desintegración radiactiva, etc.) para generar números aleatorios, pero la librería estándar de C++ no proporciona directamente este tipo de generadores.
Motores de números aleatorios comunes
| Motor | Descripción |
|---|---|
std::default_random_engine | Motor de números aleatorios predeterminado, cuya implementación depende del compilador específico. |
std::minstd_rand | Motor de congruencia lineal, produce secuencias de números pseudoaleatorios uniformes. |
std::mt19937 | Algoritmo Mersenne Twister, adecuado para la generación de números aleatorios de propósito general. |
std::mt19937_64 | Algoritmo Mersenne Twister de 64 bits. |
std::ranlux24_base | Motor simplificado de resta con acarreo, utilizado para generación de alta calidad. |
std::knuth_b | Generador de números aleatorios de barajado de Knuth. |
Motores comunes comostd::mt19937debido a su alta velocidad de generación y alta calidad, son generadores de números aleatorios ampliamente recomendados. El generador también puede utilizar elseed()método para especificar la semilla, lo que facilita la generación de secuencias pseudoaleatorias repetibles.
Tipos de distribución de números aleatorios
1. Distribución uniforme
| Distribución | Descripción |
|---|---|
std::uniform_int_distribution | Genera una distribución uniforme dentro de un rango de enteros. |
std::uniform_real_distribution | Genera una distribución uniforme dentro de un rango de números de punto flotante. |
std::mt19937 gen(seed); std::uniform_int_distribution<int> dist(1, 100); // 生成 1 到 100 间的整数 int random_int = dist(gen);
2. Distribución normal
| Distribución | Descripción |
|---|---|
std::normal_distribution | Distribución normal estándar, simétrica respecto al centro, comúnmente utilizada para simular fenómenos naturales. |
std::lognormal_distribution | Distribución logarítmico-normal. |
std::mt19937 gen(seed); std::normal_distribution<> dist(0, 1); // 平均值为0,标准差为1 double random_normal = dist(gen);
3. Distribución discreta
| Distribución | Descripción |
|---|---|
std::discrete_distribution | Los números aleatorios generados son un conjunto de enteros con probabilidades específicas. |
std::bernoulli_distribution | Distribución de Bernoulli, solo generatrueofalse。 |
std::binomial_distribution | Distribución binomial. |
std::mt19937 gen(seed);
std::discrete_distribution<int> dist({40, 10, 50}); // 概率为40%、10%、50%
int random_discrete = dist(gen);
Sintaxis
Usar<random>Los pasos básicos para usar la librería son los siguientes:
- Incluir el archivo de encabezado
<random>。 - Crear un objeto generador de números aleatorios.
- Utilizar la clase de distribución para generar números aleatorios.
Ejemplo
Generar números aleatorios básicos
Ejemplo
#include <random>
int main() {
// Usar un dispositivo aleatorio para crear una semilla aleatoria
std::random_device rd;
// Inicializar el generador de números aleatorios Mersenne Twister con la semilla aleatoria
std::mt19937 generator(rd());
// Generar un número aleatorio
std::cout << "Random number: " << generator() << std::endl;
return 0;
}
Resultado de salida:
Random number: 3499211612
Nota:Cada vez que se ejecuta el programa, los números aleatorios generados pueden ser diferentes.
Usar distribución uniforme
Ejemplo
#include <random>
int main() {
// Crear un generador de números aleatorios
std::mt19937 generator;
// Crear un generador de números aleatorios con distribución uniforme, con un rango de 1 a 10
std::uniform_int_distribution<int> distribution(1, 10);
// Generar e imprimir 5 números aleatorios
for (int i = 0; i < 5; ++i) {
std::cout << "Random number: " << distribution(generator) << std::endl;
}
return 0;
}
Resultado de salida:
Random number: 7 Random number: 10 Random number: 6 Random number: 2 Random number: 4
Cada vez que se ejecuta el programa, la secuencia de números aleatorios de salida puede ser diferente.
Usar distribución normal
Ejemplo
#include <random>
#include <iomanip>
int main() {
// Crear un generador de números aleatorios
std::mt19937 generator;
// Crear un generador de números aleatorios con distribución normal, media 0 y desviación estándar 1
std::normal_distribution<double> distribution(0.0, 1.0);
// Establecer el formato de salida, conservando dos decimales
std::cout << std::fixed << std::setprecision(2);
// Generar e imprimir 5 números aleatorios
for (int i = 0; i < 5; ++i) {
std::cout << "Random number: " << distribution(generator) << std::endl;
}
return 0;
}
Random number: -0.15 Random number: 0.13 Random number: -1.87 Random number: 0.46 Random number: -0.21
Generar números aleatorios con diferentes distribuciones usando el motor mt19937:
Ejemplo
#include <random>
int main() {
// 1. Configurar la semilla y el motor de números aleatorios
std::random_device rd; // El dispositivo aleatorio genera la semilla
std::mt19937 gen(rd()); // Motor Mersenne Twister
// 2. Enteros con distribución uniforme
std::uniform_int_distribution<> dist_int(1, 100);
std::cout << "Uniform integer: " << dist_int(gen) << std::endl;
// 3. Números de punto flotante con distribución uniforme
std::uniform_real_distribution<> dist_real(0.0, 1.0);
std::cout << "Uniform real: " << dist_real(gen) << std::endl;
// 4. Distribución normal
std::normal_distribution<> dist_normal(0, 1);
std::cout << "Normal: " << dist_normal(gen) << std::endl;
// 5. Distribución discreta
std::discrete_distribution<> dist_discrete({10, 20, 70});
std::cout << "Discrete: " << dist_discrete(gen) << std::endl;
return 0;
}
Adaptadores de números aleatorios
Los adaptadores de números aleatorios permiten ajustar el comportamiento de generación; principalmente hay dos tipos de adaptadores:
std::discard_block_engine: descartan una cierta cantidad de valores generados, conservando solo los valores a intervalos especificados, para reducir la aleatoriedad.std::independent_bits_engine: generan números aleatorios con un número específico de bits, lo que facilita la generación directa de datos binarios.
Ejemplo
#include <random>
int main() {
std::random_device rd;
std::mt19937 gen(rd());
std::discard_block_engine<std::mt19937, 3, 2> discard_engine(gen);
std::cout << "Discard block random number: " << discard_engine() << std::endl;
return 0;
}
Usos comunes
- Usar una semilla para generar secuencias aleatorias repetibles: especificar la misma semilla hace que cada ejecución genere la misma secuencia.
- Generar números aleatorios con diferentes distribuciones: elegir la función de distribución adecuada para el escenario de aplicación permite simular mejor problemas reales.
- Ajustar el rendimiento del generador: usar diferentes motores aleatorios para equilibrar el rendimiento de generación y la precisión.