Engines are responsible for generating uniformly distributed random numbers. One such provided engine is the Mersenne Twister engine. Distributions use the output of engines to mold the numbers to a specific distribution.
Consider the following example.
mt19937 engine(static_cast<unsigned long>(time(NULL)));
exponential_distribution<double> dist;
cout << dist(engine) << endl;
The output is a single random number, following the exponential distribution. Now let's say we want to use this in a call to
generate_n
with a lambda:
mt19937 engine(static_cast<unsigned long>(time(NULL)));
exponential_distribution<double> dist;
generate_n(ostream_iterator<double>(cout, "\n"), 20, [&dist,&engine]() -> double { return dist(engine); });
You're probably thinking that a simple
for
loop would be much cleaner here, and I don't disagree. However, there is one other thing we can do:
mt19937 engine(static_cast<unsigned long>(time(NULL)));
exponential_distribution<double> dist;
variate_generator<mt19937, exponential_distribution<double>> gen(engine, dist);
generate_n(ostream_iterator<double>(cout, "\n"), 20, gen);
That's right --
variate_generator
is provided to us so that we can encapsulate an engine along with a distribution. That way, a simple gen()
gets us a random number using the desired engine and distribution.