Beginner's Guide
    First Steps
    Input & Output
    Custom Types – Part 1
    Diagnostics
    Standard Library – Part 1
    Function Objects
    Standard Library – Part 2
    Code Organization
    Custom Types – Part 2
    Generic Programming
    Memory Management
    Software Design Basics

    Random Number Generation Random Numbers Random

    #include <random>
    random_engine_type engine {seed};
    distribution_type distribution {parameters,…};
    auto random_value = distribution(engine);
    • random numbers are produced by distributions
    • distributions use uniform random bit engines as sources of randomness
    • no single global state, several independent random engines possible
    • new distribution types can make use of existing engines
    • can change randomness sources while keeping distribution types (e.g., change a deterministic engine for one that uses hardware entropy)

    Examples

    Uniform Random Numbers Uniform Numbers

    #include <random>
    // fixed seed
    auto const seed = 123;
    // Mersenne Twister random engine:
    std::mt19937 urbg {seed};  
    // generate random ints ∈ [1,6]
    std::uniform_int_distribution<int> distr1 {1, 6};
    auto const value1 = distr1(urbg);
    auto const value2 = distr1(urbg);
    // generate random floats ∈ [-1.2,6.25)
    std::uniform_real_distribution<float> distr2 {-1.2f, 6.25f};
    auto const value3 = distr2(urbg);
    
    

    Boolean Values ("Coin Flip") Boolean Values Boolean

    #include <random>
    auto const seed = 123;
    auto urbg = std::mt19937 {seed};  
    // unfair coin (40% 'true'):
    double const p = 0.4;  
    auto flip = std::bernoulli_distribution{p};
    if (flip(urbg))  // 40% chance
      cout << "heads\n";
    else  // 60% chance
      cout << "tails\n";
    
    standard library bernoulli random distribution

    Normal Distribution Normal

    #include <random>
    auto const seed = 123;
    auto urbg = std::mt19937 {seed};  
    double const mu = 4.0; 
    double const sigma = 0.7; 
    auto norm = std::normal_distribution<double>{mu,sigma};
    auto value = norm(urbg);
    
    standard library normal random distribution

    Integers With Individual Probabilities Discrete Distribution Discrete

    #include <random>
    auto const seed = std::random_device{}();
    auto urbg = std::mt19937{seed};  
    std::vector<double> ws {1.0, 1.5, 0.5, 2.0};
    std::discrete_distribution<int> distr {begin(ws)end(ws)};
    std::vector<int> histo (ws.size(), 0);
    int const N = 100000;
    for (int k = 0; k < N; ++k) {
      auto const i = distr(urbg);
      ++histo[i];
    }
    std::cout << "Histogram:\n";
    for (auto x : histo) {
      auto const size = int(30 * x/double(N));
      cout << std::string(size,'-') << "o\n";
    }
    
    
    Histogram:
    ------o
    --------o
    ---o
    -----------o
    standard library discrete random distribution

    How To How To

    Seed Engines

    • with an integer of type  engine_type::result_type
    • or with a seed sequence
    • either in the constructor:  engine_type { seed }
    • or with member function  .seed( seed };
    #include <random>
    #include <chrono>  // clocks
    auto e = std::mt19937{};
    
    // seed engine with a constant e.seed(123);
    // … or with system clock ticks auto const ticks = std::chrono::system_clock::now().time_since_epoch().count(); e.seed(ticks);
    // … or with hardware entropy auto const hes = std::random_device{}(); e.seed(hes);
    // … or with a seed sequence std::seed_seq s {1,5,3,7,0,9}; e.seed(s);
    auto distr = std::uniform_real_distribution{-11.0, 15.3}; cout << distr(e) << '\n';

    Make Custom Generators Generators

    Lambda Generator Lambda

    • initialize engine & distribution in lambda capture
    • important: lambda must be marked mutable because internal state of engine and distribution need to change with each call
    #include <random>
    auto const seed = std::random_device{}();
    auto coin_flip = [
      // init-capture engine + distribution:
      urbg = std::mt19937{seed},
      distr = std::bernoulli_distribution{0.5}
    ]() mutable -> bool { return distr(urbg); };
    // use generator:
    cout << coin_flip() << '\n';
    
    auto roll = [ urbg = std::mt19937{seed}, distr = std::uniform_int_distribution<int>{1,6} ]() mutable -> int { return distr(urbg); }; cout << roll() << '\n';

    Custom Generator Class Func.Class

    if more control over parameters is needed

    #include <random>
    class DiceRoll {
      using engine_type = std::mt19937;
      // engine + distribution as members:
      engine_type urbg_;
      std::uniform_int_distribution<int> distr_;
    public:
      using seed_type = engine_type::result_type;
      // constructor:
      explicit 
      DiceRoll (int sides, seed_type seed = 0) noexcept: 
        urbg_{seed}, distr_{1,sides} {}
      // allows to re-seed
      void seed (seed_type s) noexcept {     urbg_.seed(s); }
      // call operator:
      int operator () () noexcept {     return distr_(urbg_); }
    };
    
    int main () {
      auto const seed = std::random_device{}();
      DiceRoll roll_d20 {20, seed};
      std::cout << roll_d20() << '\n';
    }

    shuffle shuffle C++11

    #include <algorithm>
    #include <random>
    // 32 bit mersenne twister engine
    auto const seed = std::random_device{}();
    auto reng = std::mt19937{seed};
    std::vector<int> v {0,1,2,3,4,5,6,7,8};
    shuffle(begin(v)+2, begin(v)+7, reng);  
    for (int x : v) { cout << x <<' '; }  // 0 1 … 7 8
    
    #include <algorithm>
    #include <random>
    // 32 bit mersenne twister engine
    auto const seed = std::random_device{}();
    auto reng = std::mt19937{seed};
    std::vector<int> v {2,3,4,5,6};
    std::ranges::shuffle(v, reng);  
    for (int x : v) { cout << x <<' '; }  
    

    Distribution Types Overview Distributions Distributions

    Common Interface

    • distribution_type distr; // with default params
    • distribution_type distr { parameter_object };
    • distribution_type distr { parameter1, parameter2,… parameter};
    auto random_value = distribution_object(engine_object);
    • distr.min() → smallest obtainable value
    • distr.max() → largest obtainable value
    • distr.param() → parameter object
    • distr.reset() :  reset internal state
    distribution_type::param_type pars { parameter1, parameter2,… parameter};
    distribution_type distr1 { pars };
    distribution_type distr2 { pars };
    distribution_type distr3 { distr1.param() };

    distr.a().b().m().n().s().alpha().beta().lambda().mean().stddev() …

    Uniform Distributions

    uniform_int_distribution<IntegerType> {a=0,b=∞}
    uniform_real_distribution<RealType> {a=0,b=1}

    Sampling Distributions

    discrete_distribution<IntegerType>
    piecewise_constant_distribution<RealType>
    piecewise_linear_distribution<RealType>

    Bernoulli Distributions

    bernoulli_distribution {p=0.5}
    binomial_distribution<IntegerType> {t=1,p=0.5}
    negative_binomial_distribution<IntegerType> {k=1,p=0.5}
    geometric_distribution<IntegerType> {p=0.5}

    Normal Distributions

    normal_distribution<RealType> {μ=0,σ=1}
    lognormal_distribution<RealType> {m=0,s=1}
    chi_squared_distribution<RealType> {n=1}
    cauchy_distribution<RealType> {a=0,b=1}
    fisher_f_distribution<RealType> {m=1,n=1}
    student_t_distribution<RealType> {n=1}

    Poissson Distributions

    poisson_distribution<IntegerType> {μ=1}
    exponential_distribution<RealType> {λ=1}
    gamma_distribution<RealType> {α=1,β=1}
    weibull_distribution<RealType> {a=1,b=1}
    extreme_value_distribution<RealType> {a=0,b=1}

    Overview Sheets  (click to enlarge)

    Engine Types Overview Engines Engines

    engine_type eng;
    engine_type eng { IntegerSeed };
    engine_type eng { SeedSequence };
    eng.seed(IntegerSeed);
    eng.seed(SeedSequence);
    eng.discard(steps);
    engine_type::result_type

    Linear Congruential Engines LCG

    std::minstd_rand0  // 1969 by Lewis, Goodman, Miller
    std::minstd_rand   // 1993 by Park, Miller, Stockmeyer

    Mersenne Twister Engines M.Twister

    std::mt19937     // 32-bit, Matsumoto and Nishimura, 1998
    std::mt19937_64  // 64-bit, Matsumoto and Nishimura, 2000

    Subtract With Carry Engines SWC

    std::ranlux24_base
    std::ranlux48_base

    Engine Adaptors

    std::ranlux24  // discard_block_engine
    std::ranlux48  // discard_block_engine
    std::knuth_b   // shuffle_order_engine

    depends on compiler/platform; often a linear congruential engine

    Non-Deterministic Entropy Source random_device

    represents a non-deterministic random number generator that e.g., uses a hardware entropy source.

    Standard library implementations are allowed to use a pseudo-random number engine as random_device if there is no non-deterministic entropy source available.

    std::random_device rd;
    bool non_deterministic = rd.entropy() >  0;
    bool deterministic     = rd.entropy() == 0;
    auto distr = std::uniform_real_distribution{-1.0,1.0};
    auto num = distr(rd);

    Some (older) standard library implementations return 0 despite its random_device beeing non-deterministic.