Every implementation of the C++ Standard Library like one included to Embarcadero RAD Studio C++ compilers provides two ways for (pseudo-)random numbers generation: old-fashioned facilities from <cstdlib>
and modern facilities provided by <random>
.
Facilities from <cstdlib>
There are two very simple functions provided by the C random library: std::srand()
and std::rand()
. The former seeds the pseudo-random number generator and the later generates a pseudo-random number from range [0, RAND_MAX]
, where RAND_MAX
is an implementation defined integer constant that is guaranteed be at least 32767
.
Please keep in mind, that a sequence of random numbers from the same seed is repeatable! Hence, it’s important to seed the random number generator by some new integer value, such as the time point picked up from system clock, before calling of std::rand()
.
Facilities from <random>
There are four categories of entities in modern part (available since C++11) of random number library: uniform random number generators, random number engines, random number engine adaptors, and random number distributions:
Uniform random number generator is intended to yield unsigned integer values in the range of possible results.
Random number engine is a uniform random number generator with a state determined by a seed.
Random number engine adaptor is a random number engine intended to transform values from another random number engine to produce values with modified randomness properties by using some algorithm.
Random number distribution is a function to yield values that are distributed according to an associated mathematical probability density function.
Binding a number distribution to an engine yields a generator that produces a sequence of values according to a distribution. For example, let’s bind Normal Distribution to a default random engine (which provides the behavior for relatively casual, inexpert, and/or lightweight use):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#include <iostream> // to print the histogram #include <map> // to store the histogram #include <random> int main() { auto generator = [ d = std::normal_distribution<double>{100.0, 70.0}, e = std::default_random_engine{}]() mutable { return d(e); }; // The histogram will store pairs: // {random value, frequency of occurrence} std::map<int, int> histogram; for (int i = 0; i < 10000; ++i) histogram[generator()]++; // increase frequency for (const auto& pair : histogram) std::cout << pair.second << "\n"; // print frequency } |
The visualization of the output produced by the program above might looks like the following: