C++ Standard Library <random>

In the C++ standard library<random>The header file provides a set of tools for generating random numbers, covering everything from simple uniform distributions to complex discrete distributions, offering a wide range of options for applications that require random numbers. These tools are very useful in fields such as simulation, game development, and cryptographic algorithms.

<random>It not only supports generating pseudo-random numbers, but also supports seed control, various probability distributions, etc., allowing developers to flexibly generate sequences of random numbers that meet specific requirements.

<random>The library consists of the following three main components:

  1. Random number engine: The core of generating pseudo-random numbers, used to control the reproducibility and randomness of the generation process.
  2. Random number distribution: Controls the type of probability distribution that the generated values follow.
  3. Random number adapter: allows adjusting engine behavior, such asdiscard_blockand other adapters.

In C++, random number generators (Random Number Generator, RNG) can be divided into two main categories:

  • Pseudorandom number generator: They use deterministic algorithms to generate seemingly random sequences. These sequences are theoretically predictable, but are generally random enough for most applications.
  • True random number generator: They generate random numbers based on physical processes (such as thermal noise, radioactive decay, etc.), but the C++ standard library does not directly provide such generators.

Common random number engines

EngineDescription
std::default_random_engineDefault random number engine, with an implementation that depends on the specific compiler.
std::minstd_randLinear congruential engine, producing a uniform sequence of pseudo-random numbers.
std::mt19937Mersenne Twister algorithm, suitable for general-purpose random number generation.
std::mt19937_6464-bit Mersenne Twister algorithm.
std::ranlux24_baseSimplified subtract-with-carry engine, used for high-quality generation.
std::knuth_bKnuth shuffle random number generator.

Common engines such asstd::mt19937Because of its fast generation speed and high generation quality, it is a widely recommended random number generation engine. The generator can also useseed()Method to specify the seed, facilitating the generation of reproducible pseudo-random sequences.

Random number distribution types

1. Uniform distribution

DistributionDescription
std::uniform_int_distributionGenerates a uniform distribution over a range of integers.
std::uniform_real_distributionGenerates a uniform distribution over a range of floating-point numbers.
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(1, 100); // 生成 1 到 100 间的整数
int random_int = dist(gen);

2. Normal distribution

DistributionDescription
std::normal_distributionStandard normal distribution, centrally symmetric, often used to simulate natural phenomena.
std::lognormal_distributionLognormal distribution.
std::mt19937 gen(seed);
std::normal_distribution<> dist(0, 1); // 平均值为0,标准差为1
double random_normal = dist(gen);

3. Discrete distribution

DistributionDescription
std::discrete_distributionGenerates random numbers as integers with a set of specific probabilities.
std::bernoulli_distributionBernoulli distribution, which only generatestrueorfalse。
std::binomial_distributionBinomial distribution.
std::mt19937 gen(seed);
std::discrete_distribution<int> dist({40, 10, 50}); // 概率为40%、10%、50%
int random_discrete = dist(gen);

Syntax

Usage<random>The basic steps of the library are as follows:

  • Include Header Files<random>。
  • Create a random number generator object.
  • Use the distribution class to generate random numbers.

Example

Generate basic random numbers

Example

#include <iostream>
#include <random>

int main() {
    // Use a random device to create a random seed
    std::random_device rd;
   
    // Use the random seed to initialize the Mersenne Twister random number generator
    std::mt19937 generator(rd());

    // Generate a random number
    std::cout << "Random number: " << generator() << std::endl;

    return 0;
}

Output result:

Random number: 3499211612

Note:Each time the program runs, the generated random numbers may be different.

Using uniform distribution

Example

#include <iostream>
#include <random>

int main() {
    // Create a random number generator
    std::mt19937 generator;

    // Create a uniformly distributed random number generator with a range from 1 to 10
    std::uniform_int_distribution<int> distribution(1, 10);

    // Generate and print 5 random numbers
    for (int i = 0; i < 5; ++i) {
        std::cout << "Random number: " << distribution(generator) << std::endl;
    }

    return 0;
}

Output result:

Random number: 7
Random number: 10
Random number: 6
Random number: 2
Random number: 4

Each time the program runs, the output random number sequence may be different.

Using normal distribution

Example

#include <iostream>
#include <random>
#include <iomanip>

int main() {
    // Create a random number generator
    std::mt19937 generator;

    // Create a normally distributed random number generator with mean 0 and standard deviation 1
    std::normal_distribution<double> distribution(0.0, 1.0);

    // Set the output format to two decimal places
    std::cout << std::fixed << std::setprecision(2);

    // Generate and print 5 random numbers
    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

Using the mt19937 engine to generate random numbers with different distributions:

Example

#include <iostream>
#include <random>

int main() {
    // 1. Set the seed and random number engine
    std::random_device rd; // Random device generates the seed
    std::mt19937 gen(rd()); // Mersenne Twister engine

    // 2. Uniformly distributed integers
    std::uniform_int_distribution<> dist_int(1, 100);
    std::cout << "Uniform integer: " << dist_int(gen) << std::endl;

    // 3. Uniformly distributed floating-point numbers
    std::uniform_real_distribution<> dist_real(0.0, 1.0);
    std::cout << "Uniform real: " << dist_real(gen) << std::endl;

    // 4. Normal distribution
    std::normal_distribution<> dist_normal(0, 1);
    std::cout << "Normal: " << dist_normal(gen) << std::endl;

    // 5. Discrete distribution
    std::discrete_distribution<> dist_discrete({10, 20, 70});
    std::cout << "Discrete: " << dist_discrete(gen) << std::endl;

    return 0;
}

Random number adapter

Random number adapters allow adjusting the generation behavior; there are two main types of adapters:

  1. std::discard_block_engine: Discards a certain number of generated values and retains only those at specified intervals, used to reduce randomness.
  2. std::independent_bits_engine: Generates random numbers with a specified number of bits, making it easy to directly generate binary data.

Example

#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;
}

Common usage

  • Use a seed to generate a reproducible random sequence: specifying the same seed makes each run generate the same sequence.
  • Generate random numbers with different distributions: Choose a distribution function that matches the application scenario to better simulate real-world problems.
  • Adjusting generator performance: Use different random engines to balance generation performance and accuracy.
other extensions