Another powerful use of loops is to run simulations involving chance. Sometimes, perfectly modeling something complex like the path of a hurricane is impossible due to limits in either our understanding of the thing being modeled or the computational power available. To handle imperfect knowledge, we can assign probabilities to possible events and then βroll the diceβ. To see what happens. If we repeat that simulation many times and our estimated probabilities are accurate, we can learn about the possible outcomes and how likely each one is. This is often referred to as a Monte Carlo simulation (named after Europeβs answer to Las Vagas).
To do this kind of simulation, we need to generate random numbers. Computers struggle to produce truly random values - they are deterministic machines that are supposed to always do what is expected. But they can produce pseudo-random numbers. These are numbers generated by a formula that produces a sequence of numbers that appear random.
To produce reliable results in simulations, or to provide security in an encryption algorithm that relies on generating randomness, the generator we use needs to produce a βhigh qualityβ of randomness βan unpredictable sequence of values where every possible value is as likely as every other to appear next.
In C++ unfortunately, generating high quality random numbers requires uses of some slightly complex code. To make this process easier, we will rely on a custom library called SimpleRandom. We will learn later on how to build libraries like it. But for now, just recognize that any code sample that has import SimpleRandom; in it makes use of this library. The library provides three functions:
/**
* @brief Seeds the random number generator. Calling this function with an integer
* will seed the generator with that value.
*
* @param x Seed value to use.
*
* @note If you don't call this function, the generator will
* be seeded with a random value.
*/
void seedRNG(unsigned int x);
/**
* @brief Generates a random integer in the range [min, max].
*
* @param min The minimum value of the range.
* @param max The maximum value of the range.
* @return A random integer in the range [min, max].
*/
int randRange(int min, int max);
/**
* @brief Generates a random double in the range [0.0, 1.0).
*
* @return A random double in the range [0.0, 1.0). i.e. 0-0.9999...
*/
double randDouble();
Most of the time, we will just call something like randRange(1, 6) to get a random number from 1 to 6. Try running this program to generate 10 random dice rolls between 1 and 6. Every time you run it you should get a different sequence:
The seed value is the value that is used to start the pseudo-random sequence. Normally we want the seed to be as random as possible (using something like the number of milliseconds on the system clock or random electrical noise for the randomness). But if you want a program to always generate the same sequence of values, perhaps because you are trying to debug it, you can specify a seed by calling seedRNG (Random Number Generator. You normally only do this ONCE when you first start using the random number generator.
This version of the same program seeds the number generator. Every time you run it you should get the same βrandomβ sequence. If you change the seed you will get a new sequence.
There is also a simpler way to make random numbers in C++ using the functions rand and srand from the cstdlib. Those functions have some significant limitations in terms of the quality of number they generate. So we will rely on the SimpleRandom library that makes the complex code easier to use for basic activities.