Making A Random Number Generator Random Number Generator Rand.Gen.
Reminder: Standard Library Paradigm
Sources of randomness are decoupled from distributions
- distribution objects produce random numbers
- uniform random bit engine objects act as sources of randomness
#include <random>
random_engine_type engine {seed};
distribution_type distribution {parameters,…};
auto random_value = distribution(engine);
Question
How to make a single random generator object that ties both a distribution object and an engine object together?
- 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>
#include <iostream>
int main () {
// obtain some seed
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:
bool coin = coin_flip();
std::cout << "coin: " << coin << '\n';
auto roll = [
urbg = std::mt19937{seed},
distr = std::uniform_int_distribution<int>{1,6}
]() mutable -> int { return distr(urbg); };
int const num = roll();
std::cout << "num: " << num << '\n';
}
if more control over parameters is needed
#include <random>
#include <iostream>
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';
}
Comments…