C++11 normal distribution random number generator

The C++11 normal distribution (or normal_distribution) produces random numbers x using the respective discrete probability function of the distribution-the function is shown at the end of the post.

Link :C++ random number generator
 
C++11 normal distribution

The distribution class declaration is shown below.

template<class RealType = double>
  class normal_distribution;

The class default type is double type and note this distribution can generate only floating point type values or real numbers.

The distribution is based on the the normal distribution of the probability distribution.

The types and member functions of the class is shown below.


Types

typedef RealType result_type; 

typedef unspecified param_type;

The RealType is a type definition of the template type and the param_type is a structure but note the definition of the param_type will alter from compiler to compiler.



Constructors and reset function

explicit normal_distribution(RealType mean = 0.0, RealType stddev = 1.0);

explicit normal_distribution(const param_type& parm);

void reset( );

The first constructor accepts two parameters ‘mean’ and ‘stddev’ whose default values are 0 and 1.These default values will be same in all compiler.The uses of these two parameters is used in finding the probability of the random values in the distribution.The relation 0 < stddev on ‘stddev’ should hold.

The second constructor accept param_type object and in this case the values of ‘mean’ and ‘stddev’ is deduced from the ‘mean’ and ‘stddev’ values of the param_type object.

normal_distribution< > nd ;

normal_distribution<float > nd1;

normal_distribution< float >::param_type pt(56.01 , 6.7 ) ;

normal_distribution< long double &gt: nd2(pt) ; //error! , type of pt is float but type of nd2 is double type

reset()

The reset( ) function reset the state of the distribution.


Generating functions

template<class URNG>
  result_type operator( )(URNG& g); 

template<class URNG>
result_type operator( )(URNG& g, const param_type& parm);
the first operator() function

The generated random sequence is obtained using the operator() function.The first overloaded operator() accept URNG(Uniform Random Number Generator) or engine.

normal_distribution< > nd ;

default_random_engine dre ;

cout<< nd(dre) << ” ” << nd(dre) << endl ;

Output in Code::blocks,

-1.08682   -0.121966

the second operator( ) function

The second overloaded operator( ) function accept URNG and param_type object.

normal_distribution< >nd ;

normal_distribution< float >::param_type pt(56.01 , 6.7 ) ;

linear_congruential_engine<unsigned int , 193703 , 0 , 83474882 > lce ;

cout<< nd(lce , pt) << ” ” << nd(lce , pt) << endl ; 

Output in Code::blocks,

55.132   55.9866



Property functions

RealType mean() const;

RealType stddev() const;

param_type param() const;

void param(const param_type& parm); 

result_type min() const;

result_type max() const; 
mean() function

This function returns the ‘mean’ value of the distribution.

normal_distribution< >nd ,

nd1( 900 , 10);

cout<< nd.mean() << endl
<< nd1.mean() ;

Output,

0
900

stddev() function

This function returns the ‘stddev’ value of the distribution.

normal_distribution< >nd ,

nd1( 900 , 10);

cout<< nd.stddev() << endl
<< nd1.stddev() ;

Output,

1
10

param()

This function returns the param_type object.

normal_distribution< >nd( 123 , 893);

cout<< nd.param().mean() << endl
<< nd.param().stddev() ;

Output,

123
893

param(param_type)

Using this function we can change the ‘mean’ and ‘stddev’ value of the distribution to the ‘mean’ and ‘stddev’ value of the param_type object by passing the param_type object.

normal_distribution<float > nd(5000 , 100);

cout<< nd.mean() << endl ;

normal_distribution< float >::param_type pt( 56.01 , 6.7 ) ;

nd.param( pt );

cout<< evd.mean() ;

Output,

5000
56.01

min() function

The min() returns the smallest value the distribution can generate,which is the value 0.

normal_distribution<float > nd(5000 , 100);

cout<< nd.min( );

Output,

0

max() function

The max() returns the largest value the distribution can generate.It returns the value of numeric_limits<result_type>::max().

normal_distribution<float > nd(5000 , 100);

cout<< nd.max( );

Output,

3.40282e+038


operator== and operator!= functions

These two functions check the parameters of the two distribution objects.If the two parameters are equal the operator== returns 1 and operator!= returns 0.Note the function operator== always returns true(ans operator!= always false) as long as the ‘mean’ and ‘stddev’ of the two comparison objects are equal not matter what state the two objects is in.

normal_distribution<float > nd1( 90 , 9.56) ,

nd2( 0.23 , 5.69 ) , nd3( 90 , 9.56 ) ;

cout<< ( nd==nd1 ) << endl
 << ( nd!=nd1 ) << endl
 << ( nd==nd3); 

Output ,

0
1
1



operator>> and operator<< functions

These two operators allows you to save the state of the engine and the distribution.Using the operator>> function we can save the sate of the distribution to the ‘stringstream’ type object.And using the operator<< function we can obtain the state of the distribution or engine save in the ‘stringstream’ object and reassign it to the distribution’s or engine’s object.The same state can help in producing the same sequence which was generated earlier when that state was achieved.Note to reproduce the same state not only the distribution’s state but also the engine’s state must be same.

In the code below we will try to save the distribution state and also save the engine’s state,in this way we will be able to reproduce the same random sequence.

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

using namespace std ;

int main( )
{
stringstream engState ,  //object to save the engine state
  disState ;  //object to save the distribution state

normal_distribution<> ndIO1(25.6 , 90.4) , ndIO2(25.6 , 90.4) ;

default_random_engine dre1 , dre2 ;

cout<< ndIO1(dre1) << endl ;  //first random number

disState<< ndIO1 ;  //Save the 2nd distribution state of ndIO to disState
engState<< dre1 ;  //Save the 2nd engine state of dre1 to engState

cout<< “Second and third state output of ndIO1 and dre1 \n”;
cout<< ndIO1( dre1 ) << ” ” ;
cout<< ndIO1(dre1) << endl ;

disState>> ndIO2 ;  //reassign the distribution state saved in disState to ndIO2
engState>> dre2 ;  //reassign the engine’s state saved in engState to dre2

cout<< “\n\nOutputting the random sequence using ndIO2 and dre2 current state\n”;
cout<< ndIO2( dre2 ) << ” ” ;
cout<< ndIO2( dre2 ) << endl ;

cin.get( );
return 0;
}

Output in Code::Blocks ,

14.5743
Second and third state output of ndIO1 and dre1
-72.6484 87.4598
 
Outputting the random sequence using ndIO2 and dre2 current state
-72.6484 87.4598

The second sate of ndIO1 and dre1 has been assigned to ndIO2 and dre2,so the numbers generated by the second sate and it’s consecutive state of ndIO1 and dre1 will be same as the sequence generated by the ndIO2 and dre2 current state and it’s consecutive state.Note reproducing the same sequence can be useful for debugging purpose.


Side note

normal_distribution produces random numbers x distributed according to the probability density function,

C++11 normal distribution

Note in normal_distribution the generated sequence will have more values that revolve around the ‘mean’ value.