C++11 random number generator


C++11 provides a library header file known as <random>.This header file include many templates and functions which help generate random numbers of different types(integer or floating point values with or without mathematical significance) and under the specification of the user it can also generate random numbers within certain range of value.In C++(including C++11) the header <random> is known as the random number generator since the header’s sole purpose is to help generate random numbers of utmost randomness.

The random number generator of C++11 consists of two important aspects that make up the random number generator:engine and distribution.These two are the deciding factors of how the random numbers are generated,the degree of randomness and the range within which the random number is obtained.Note here the degree of randomness is important for every random number generator.It determine the quality of the random number generator, the more is the degree of randomness the better it is as a random number generator.Random number generator having lesser degree of randomness can be predictable and it may not be a good choice.So degree of randomness is one of the most important property that must be taken into account when choosing a random number generator.The random number generated by the library as it is may not have a good degree of randomness,what might actually help generate a perfect random number and how to obtain them will be discussed later.

The engine and distributions are discuss in more detail below.

Engine

When we say ‘random number generator engine or ‘basic engine‘ or just ‘engine‘ we denote the source of the random numbers.They can also refer to the mechanism behind which the random number is generated.It is also the most important element of any random number generator.Without ‘engine’ there would be no random number.

There are many types of ‘engine’ provided by the <random> header file :default_random_engine,linear_congruential_engine,mersenne_twister_engine etc. are some of the basic engine,visit the link ( C++ random header ) to view all the engine list.Note the engine itself is sufficient to get a list of random numbers.A code example is provided below and uses the engine default_random_engine.In the program we simply try to generate 10 random numbers.

Link : C++11 random default_random_engine

Code example

#include <iostream>
#include <random> //necessary!

using namespace std;

int main( )
{
default_random_engine dre ; //’engine’ declaration

for( auto i=0 ; i<5 , i++ )
{
cout<< dre( ) << endl ; //get the random number
}

cin.get( );
return 0;
}

Output in Code::Blocks,

16807
282475249
1622650073
984943658
1144108930

Output in Visual Studio ,

3499211612
581869302
3890346734
3586334585
545404204

The output in Code::Blocks and Visual studio are different because the default_random_engine is an implementation-specific type engine.It will give different output in different compiler.And note it is the only implementation-specific engine.Other engines like the linear_congruential_engine,mersenne_twister_engine,etc. are not implementation-specific engine and so it will generate the same random number in different compiler.For instance let’s take the engine linear_congruential_engine and try to generate a random number ;this engine actually generate a pseudorandom numbers(a not so random number).You will see that the engine gives the same output in Code::blocks and Visual Studio.

Link : C++11 random linear_congruential_engine

Code example

linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> lce ;

for(auto i=0 ; i<5 ; i++ )
{
cout<< lce( ) << endl ;
}

Output in Code::block and Visual Studio,

16807
1154976
582795
365602
723951

Engine adapters

Engine adapters are also engine but they utilize the random numbers generated by the basic engine to produce a new random numbers having different properties from the original random number produce by the basic engine.In engine adapter the basic engine used is known as the base engine.There are three engine adapters in C++ :discard_block_engine , independent_bits_engine and shuffle_order_engine.For these engine adapters you can choose any of the basic engine as their base engine.A code example is given below.

Code example

discard_block_engine< linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> dbe; //base engine is linear_congruential_engine

discard_block_engine< default_random_engine , 1 , 90 > dbe1 ; //bass engine is default_random_engine

 

Engine with predefined parameters or predefined engine

There are some engines whose parameters are fixed such engines are known as predefined engine.Predefining the parameters will generate random values from the predefined ranges,thus you cannot expand the range from which the number is obtain and also predefined engine have the same degree of randomness.Using predefined engines will always give the same output in all compiler.Engine like minstd_rand0,minstd_rand,mt19937,etc. are some of the predefined engines,visit the link (C++11 random header) to view all the predefined engines list.A code example is given below which uses the predefined engine ‘mt19937‘.This engine is a type definition of the ‘mersenne_twister_engine‘.

Code example

mt19937 mt ; ///declaration of ‘mt19937’ engine

for(auto i=0 ; i<5 ; i++)
{
cout<< mt( ) << endl ;
}

Output in Code::blocks,

3499211612
581869302
3890346734
3586334585
545404204

Try running the code in Visual Studio or in any other compiler you will get the same output.

Link : Difference between engines and predefined engines

What is ‘seed’ of an engine?

In C <ctsdlib> library the ‘srand‘ function acts as a seed for the ‘rand‘ function.In C++11 engine the concept of ‘seed’ is same as that of the <cstdlib> ‘srand’ function.Seed is nothing but some values-it can be any values- that can alter the state of the engine.A state of an engine refer to the condition or event that dictate which number should be generated as the random number.Altering the state of the ‘engine’ can help generate random number completely different from the random number which would have been generated in it’s consecutive state or the initial state.

To make the understanding of the ‘seed’ concept easier,let’s take the second code example given in this post-the code that uses ‘linear_congruential_engine‘.If you run the code,say ten times you will get the same output 10 times this is because the initial state of the engine is always the same.Now let’s try providing a ‘seed’ to the instance of the linear_congruential_engine and examine the output.Note a seed is usually provided by passing it to the engine constructor.

Link : C++ cstdlib rand

Link : C++ cstdlib srand

Code example

#include <iostream>
#include <random>
#include <ctime>

using namespace std;

int main( )
{
linear_congruential_engine<unsigned int , 16807 , 0 , 2147483> lce( time(NULL) ) ; //The value returned by time(NULL) is passed as the seed

for(auto i=0 ; i<5 ; i++ )
{
cout<< lce( ) << endl ;
}

cin.get( );
return 0;
}

Now try running the program 10 times again.Each time the program is run the output obtained varies,this is because the initial state of the engine has been changed by the ‘seed’ value obtained by calling the function ‘time(NULL)’.If one same value is provided as a seed ,the output obtained will be same for that seed value,the ‘time(NULL)’ however generate different values each second,thus the output also changes accordingly.

You can provide any function to generate the seed value,the more random is the seed value the more degree is the randomness of the number generated.The <random> header provide a class seed_seq to generate values for seed.More about this class is discussed in another post.

**Note C++11 engine can generate value of only integer type and floating point type.
The integer type supported are:short , int , long , long long their corresponding unsigned are also supported.
The floating point type supported are:float , double,long double.

A whole view of ‘engine’ and ‘predefined engines’ list is given below.

C++ random number generator



Distribution

The role of ‘distribution‘ in random number generator is to use the number generated by the ‘engine’ in a more meaningful and purposeful way.The engine simply generate a random number of the compiler’s choice thus rendering a very large values and sometimes very small unrealistic values.This behavior may not be useful to us.We may require a random values within certain range for implementing in our program and in such case the unorderly unsized generated number becomes futile.Undoubtedly in such scenario ‘distributions’ can be very helpful.By using ‘distributions’ we can restrict the range within which the random numbers should be generated.Not only that you will see that there are some distributions that help generate values base on mathematical probability density.Hence,I always like to define ‘distribution‘ as a class template which generate random numbers from your choice of restricted range and types.

There are many types of distributions in <random> header: uniform_int_distribution(a distribution to generate random integer values) ,uniform_real_distribution(a distribution to generate random real numbers), binomial_distribution(a distribution to generate binomial random numbers) , cauchy_distribution(a distribution to generate Cauchy distribution random numbers) ,etc. for all the distributions list visit the link (C++ random header file).

Since distributions are templates,to specify the type of the random numbers you want to generate pass the type as template argument.And to specify the range within which the random numbers should be generated passed the two limiting values as the arguments when the distribution objects are declared.Note passing limiting range values as constructor arguments apply only for some distributions,different distribution have different rules.To get the random values pass the engine object as an argument to the distribution ‘operator( )‘ function .A small code example is given below which uses the uniform_real_distribution and cauchy_distribution .

Code example

#include <iostream>
#include <random>
#include <iomanip>

using namespace std;

int main( )
{
default_random_engine dre ;

uniform_real_distribution<double> urd(2.456 , 3.102 );  ///’urd’ generate ‘double’ type random numbers from within the range [2.456 , 3.102]

for( auto i=0; i<5 ; i++)
{
cout<< urd(dre) << setw( 10 ) ;  ///Calling ‘urd(dre)’ get the random numbers
}

cout<< “\n\n”

cauchy_distribution<> cd ;  //The default random numbers generated will be ‘double’ type

for( auto i=0 ; i<5 ; i++ )
{
cout<< cd(dre) << setw(10) ;  //Calling ‘cd(dre)’ get the random numbers
}

cin.get( );
return 0;
}

Output in Code::blocks(uses MinGW 6.1 compiler),

2.54097   2.75229   2.59745   2.89455   3.05981

-0.587312   -10.6863   2.6071   -1.50403   -0.524788

To read more about each of the distributions please visit the random header file link and under that post you will find links to the discussion of each distributions.

Link: C++11 using auto


 



Temporary engines

Engines are said to be temporary engine if the engine object is not declared and the type is passed explicitly instead of it’s object.An instance of a temporary engine is shown below.

void generateRandomNumber(default_random_engine dre )
{

for(auto i=0 ; i<5 ; i++ )
{
cout<< dre() << ”   ” ;
}

}

int main( )
{
generateRandomNumber( default_random_engine() ); ///temporary ‘default_random_engine’ engine

cin.get( );
return 0;
}

Output in Code::block,

16807 282475249 1622650073 984943658 1144108930

Why temporary engine should not be used

All the engines have the same initial state whether it is a temporary engine or an object of the engine.But using a temporary engine instead of the engine object has a gimmick.Say when you use a ‘shuffle‘ function the third argument should be random number generator type.If you pass the third argument as a temporary engine instead of the engine object the output follows certain pattern.Consider the code below.

Code example: Include the <algorithm> header to use the ‘shuffle’ function.

vector<double> vec ={ 0.23 , 1.05 , 1.98 , 2.002 , 2.54 , 3.70 , 3.9 , 4.012 , 5 , 5.5 };

shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

Output in Code::blocks,

4.012   3.9   2.54   3.7   1.05   2.002   5.5   1.98   0.23   5

1.98   5.5   1.05   2.002   3.9   3.7   5   2.54   4.012   0.23

2.54   5   3.9   3.7   5.5   2.002   0.23   1.05   1.98   4.012

1.05   0.23   5.5   2.002   5   3.7   4.012   3.9   2.54   1.98

If you observe the output the value 3.7 occupy the 4th and 6th position alternately and the the value 2.002 also occupy the 4th and 6th position alternately.Also every number that appear first will appear in the 8th position in the next shuffling.For instance at the first output 4.01 occupy the first position in the second shuffling it appears at the 8th position,the pattern goes on for other value.

If you used an engine object instead of the temporary engine the shuffled output has no specific pattern.In this case we get an output purely of unorder random pattern.The code example is given below.

Code example

vector<double> vec ={ 0.23 , 1.05 , 1.98 , 2.002 , 2.54 , 3.70 , 3.9 , 4.012 , 5 , 5.5 };

default_random_engine dre;

shuffle( vec.begin() , vec.end() , dre ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

cout<< “\n\n”;
shuffle( vec.begin() , vec.end() , default_random_engine() ) ;

for( auto elem:vec )
{
cout<< elem << ” ” ;
}

Output in Code::Blocks ,

3.9   4.012   5   3.7   0.23   2.002   1.98   5.5   1.05   2.54

2.54   5   3.7   4.012   5.5   3.9   1.05   0.23   2.002   1.98

1.98   4.012   5   3.9   2.002   5.5   0.23   1.05   2.54   3.7

1.05   0.23   3.9   3.7   5.5   2.002   2.54   1.98   5   4.012

Now you can see that the output does not follow any pattern and we get total random output.Thus looking at the output of the two code example which uses temporary engine and which does not,we know why we should opt passing engine object for shuffling purpose.






Why ‘rand’ should not be used or why random number generator with distribution should be preferred

In C the only way to get a sequence of random numbers is to call the function ‘rand()’ repetitively.The problem with this method is the sometimes the numbers generated might be too large and it may not be suitable to work with.The usual solution to this problem -out of range generated numbers- is to use the modulo(%) and take the resultant value as the random number.For instance a code example is given below.

Code example

#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std ;

int main( )
{
srand( time(NULL) );

int reslt=rand() ,
reslt1=rand();

cout<< reslt << endl  //the output value is too large
<< reslt1 << endl ;  //the output value is too large

//Using ‘%'(modulo) operator
reslt=reslt % 250 ;
reslt1=reslt1 %2 50 ;

cout<< reslt << endl
<< reslt1 ;

cin.get( );
return 0;
}

Output in Code::blocks,

22436
32446
186
196

After using the ‘%’ operator the resultant value is smaller and workable with.

Why ‘%’ should not be used???

At first glance the using ‘%’ operator on the rand() generated value might seem a probable solution.But it isn’t so,there are two drawbacks in using the ‘%’ operator.They are given below.

i) Many pseudo-random-number generator(including the rand() function) give remainders that aren’t very random,when the integers used for the division are small.For example,it is not uncommon for successive results of rand() to be alternately even and odd.If the number used is 2,successive results of rand() % n (n is the divisor) will alternate between 0 and 1.

Code example

for(int i=0 ; i<4 ; i++)
{
cout<< rand()%2 << ” “;
}

Output

1 0 0 1

ii)If the value used for division (say ‘n’) is large, and the generated maximum value is not evenly divisible by ‘n’,some remainders will appear more often than others.For example,if the maximum is 32767 and ‘n’ is 2000,17 generated values (500,2500,…,30500,32500) would map to 500,while only 16 generated values (1500,3500,…,31500) would map to 1500.And this gets worse if ‘n’ becomes larger.

The above two reasons is enough to justify why rand() or any pseudo-random number generator should not be used.

C++11 random number generator on the other hand provides a class template known as ‘distributions’ that handle the range within which the number should be generated.Using distribution for getting the random number within our desired range guarantees that there is no discrepency in the result or the repetitiveness of the generated random sequence is
avoided.Distribution in fact solve the problem which persist when using the % operator.My advice is always prefer C++11 random number generator and distributions over the C type random number generator.


 




Saving the state of the engine to reproduce the same random sequence

As stated earlier the state of the engine determines the random sequence generated.If we can reproduce the same state of the engine we can reproduce the same sequence.This can be useful for debugging purpose and also if we can reproduce the same state we may be able to recreate the same situation.To save the state of the engine we usually use the operator<< and operator>> member functions of the engine.Note all engines have these two operators functions as there member functions.

To show you how saving the state can reproduce the same sequence,let us first consider the program shown below.In this program we will not save the state of the engine and try to get the random sequence consecutively.

Code example

#include <iostream>
#include <random>

using namesapce std ;

int main( )
{
default_random_engine dre ;

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” “;  //generate first 4 random values
}

cout<< “\n\n” ;

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” “;  //generate next 4 random values
}

cout<< “\n\n” ;

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” ” ;  //generate next 4 random values
}

cin.get( );
return 0;
}

Output in Code::blocks,

16807   282475249   1622650073   984943658

1144108930   470211272   101027544   1457850878

1458777923   2007237709   823564440   1115438165

You can see that the 12 random numbers generated are all different.And it should be as the state used by the engine when the numbers were generated are all different.

Now let us write another program,in this program we will save the sate of the engine.And after saving the sate we will reassign the saved sate to the engine’s object and generate a random sequence using the engine.Consider the code below.

Note we will use stringstream object to save the state.

Code example

#include <iostream>
#include <random>
#include <sstream>

using namesapce std ;

int main( )
{
stringstream state;

default_random_engine dre ;

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” “;  //generate first 4 random values
}

cout<< “\n\n” ;
state << dre ;  //save the state of dre in ‘state’

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” “;  //generate next 4 random values
}

cout<< “\n\n” ;
state >> dre ;  //reassign the state saved in ‘state’ to dre

for( auto i=0; i<4 ; i++ )
{
cout<< dre() << ” ” ;  //generate 4 random values
}

cin.get( );
return 0;
}

Output in Code::blocks,

16807   282475249   1622650073   984943658

1144108930   470211272   101027544   1457850878

1144108930   470211272   101027544   1457850878

The second four random numbers is same as the 3rd four random numbers because ‘dre’ is in the same state when the random numbers were generated.And this is all possible becasue the sate saved in stringstream object can be reassigned to dre and thus generating the same random sequence.


How to generate a truly random sequence.

All the random sequence generated by the engine is not truly a random sequence.To generate a true random sequence we need to set the sate of the engine in an unpredictable mannner.In other words the state of the engine at each stage must be set in such a way that it is not influence by any predictable process.Rather the seed passed to the engine must be non-predictable values produce by some nondeterministic process.For instance the time interval between each key press calculated in milliseconds.Since the time interval between key press is not influence by any natural phenomena or any sort of algorithm the values can truly be counted as random values.And passing those time interval as the seed can help generate a truly random values.

Note calling time(NULL) does not generate a random seed values since the value produce by time(NULL) is repeated evryday.