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
mutablebecause 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…