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:

  1. 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.
  2. Distribución de números aleatorios: controla el tipo de distribución de probabilidad que siguen los valores generados.
  3. Adaptador de números aleatorios: permite ajustar el comportamiento del motor, comodiscard_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

MotorDescripción
std::default_random_engineMotor de números aleatorios predeterminado, cuya implementación depende del compilador específico.
std::minstd_randMotor de congruencia lineal, produce secuencias de números pseudoaleatorios uniformes.
std::mt19937Algoritmo Mersenne Twister, adecuado para la generación de números aleatorios de propósito general.
std::mt19937_64Algoritmo Mersenne Twister de 64 bits.
std::ranlux24_baseMotor simplificado de resta con acarreo, utilizado para generación de alta calidad.
std::knuth_bGenerador 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ónDescripción
std::uniform_int_distributionGenera una distribución uniforme dentro de un rango de enteros.
std::uniform_real_distributionGenera 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ónDescripción
std::normal_distributionDistribución normal estándar, simétrica respecto al centro, comúnmente utilizada para simular fenómenos naturales.
std::lognormal_distributionDistribució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ónDescripción
std::discrete_distributionLos números aleatorios generados son un conjunto de enteros con probabilidades específicas.
std::bernoulli_distributionDistribución de Bernoulli, solo generatrueofalse。
std::binomial_distributionDistribució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 <iostream>
#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 <iostream>
#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 <iostream>
#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 <iostream>
#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:

  1. std::discard_block_engine: descartan una cierta cantidad de valores generados, conservando solo los valores a intervalos especificados, para reducir la aleatoriedad.
  2. 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 <iostream>
#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.
Otras extensiones