# Random Engine in Modern C++

Random numbers are widely used in different applications. For example, when you are playing a video game, and some random event like weather changes from a sunny day to a rainy day, we might need to be able to generate the random number in order to determine whether we need to have the weather change. In C language, we can easily generate a pseudo-random number through a rand() function call. The following code will provide us with a random number between 1 – 10, inclusively:

/* initialize random seed: */
srand (time(NULL));
/* generate secret number between 1 and 10: */
iSelect = rand() % 10 + 1;

If we do not really care about the distribution of the random number, the above approach is acceptable. If we care about the distribution, we need to consider another approach. The reason is that rand() is good to generate a uniformly distributed random number between 0 and RAND_MAX, however, if we do the modular operation, does the random number still remain uniformly distributed? No. So in this article, we will introduce the random engine and distribution objects in the <random> library of C++ and see how we can apply them.

First, let’s look at the random engine. A random engine is a stateful generator that generates random values within predefined min and max. We cannot change the range here. Not truly random — pseudorandom (which is pretty similar to rand() in terms of pseudorandom)! Please take a look at the following code with comments to see how we can define and use random engine:

 #include #include #include #include #include #include using namespace std; void printRandom(default_random_engine e){ for(int i = 0; i < 10; i++) cout << e() << " "; cout << endl; } int main(){ //Define the default random engine. default_random_engine eng; //generate two random numbers cout << "random number 1:" << eng() <> eng; //restore the state we have saved. //Now the number 5 and 6 will be exactly the same as number 3 and 4 cout << "random number 5:" << eng() < d = {1, 2, 3, 4, 5, 6, 7, 8, 9}; shuffle(d.begin(), d.end(), default_random_engine()); for (int num : d) { cout << num << " "; } cout << endl; system("pause"); return 0; }

view raw
RandomEngine.cpp
hosted with ❤ by GitHub

Note we generally utilize chrono library to generate the seed for the random engine, for more detail about the chrono library, please refer to here.  C++ standard template library provides 16 different engine types. The default engine is a balanced random number generator, with reasonable cost and randomization.

Now, let’s take a look at the distribution objects in <random> library. Suppose we want to generate a number between 1 – 5 uniformly,  what can we do? Please take a look at the following code, you will know how to do it.

 #include #include #include #include #include #include using namespace std; int main(){ unsigned int seed = chrono::steady_clock::now().time_since_epoch().count(); default_random_engine e(seed); //The range of the generated number is between [e.min(), e.max()] cout << e() << endl; //If we want to generate a random number from the range [0, 5] cout << e() % 6 << endl; // Issues with the above code: /* 1. Bad quality of randomness. The default engine can produce the * random number pretty good between [e.min(), e.max()]. With % * operation, this randomness does not holds. * 2. Can only provide a uniform distribution! */ //Uniform distribution between [0, 5], inclusive uniform_int_distribution distr(0, 5); //Now the random engine provides the randomness and distribution //object provides the distribution! cout << distr(e) << endl; //Here Range is [0, 5), 5 not included uniform_real_distribution distrR(0, 5); cout << distrR(e) << endl; //We can easily generate other distributions. //poisson distribution poisson_distribution distrP(1.0); // 1.0 is the mean cout << distrP(e) << endl; cout << "Normal distribution: " << endl; //10.0 is mean, 3.0 is standard deviation normal_distribution distrN(10.0, 3.0); vector v(20); for(int i = 0; i < 800; i++){ int num = distrN(e); //convert double to int! if(num >= 0 && num < 20){ v[num]++; //v[num] represents the frequency of num } } //Try to run the code, and you can see the distribution //yourself! for(int i = 0; i < 20; i++){ cout <<" " << std::string(v[i], '+') << endl; } cout << endl; system("pause"); return 0; }

view raw
Distributions.cpp
hosted with ❤ by GitHub

That’s all about the random engine and random distribution objects in <random> library. I hope these techniques can be helpful for your project. Thank you for reading.