Bojan Nikolic: Numerical and Quantitative Methods in C++

[website home] | [BN Algorithms]

Normally distributed random numbers

Introduction

The normal (or Gaussian) distribution is one of the most widely used distributions in numerical modelling. It is defined by:

p(X)=\frac{1}{\sigma\sqrt{2\pi}}\exp\left(-\frac{\left(X-\mu\right)^2}{2\sigma^2}\right)

where the two parameters of the distribution are \sigma^2, which is the variance, and \mu, which is the mean of the distribution.

Examples of the practical use of this distribution are widespread:

  • Simulation of observations with normally-distributed random errors
  • Generation of proposal distributions of Markov Chain Monte Carlo calculations
  • Simulations of related random processes such as:
    • Atmospheric density/water vapour content fluctuations
    • Fluctuations of prices of assets

Algorithms for generating normally distributed numbers

There are a number of available algorithms for generating normally distributed numbers. A recommended review is Thomas et al., ACM Computing Surveys, Vol. 39, No. 4, Article 11, 2007.

One of the more popular algorithms is the Box-Muller algorithm:

\rho&=\sqrt{-2\log\left(1-Y\right)}\\
X&=\rho\cos\left(2\pi Z\right)

where Y and Z are two uniform random numbers between 0 and 1 and X is the desired normally distributed random number.

Generation using boost

Numbers from the normal distribution can be easily generated using the boost random number library, which is uses the Box-Mulller algorithm described above:

#include <iostream>
#include <boost/random/normal_distribution.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/variate_generator.hpp>

int main(void)
{
  // This is the underlying integer random number generator
  boost::mt19937 igen;
  // The second template parameter is the actual floating point
  // distribution that the user wants
  boost::variate_generator<boost::mt19937, boost::normal_distribution<> >
    gen(igen, 
        boost::normal_distribution<>());

  const size_t n=10;
  for(size_t i=0; i<n; ++i)
  {
    std::cout<<gen()
             <<std::endl;
  }
}

As before in the uniform random number chapter (Uniform floating point numbers in the interval 0 to 1), we first need to initialise an integer random number generator (in this case a Mersenne Twister generator), and then use this as the source of randomness in the floating point number generator. Unlike the uniform_01 example however, in this case we need to use an explicit class which connects, called variate_generator.

The line in the program creating the connecting class is:

boost::variate_generator<boost::mt19937, boost::normal_distribution<> >
  gen(igen,
      boost::normal_distribution<>());

This is a template class which has two template parameters and two parameters to the constructor, in both cases they describe:

  1. The type and instance of the integer generator to use (in this it is the Mersenne Twister)
  2. The type and instance of the floating point distribution to generate (in this case, the normal distribution with default parameters, which means \mu=0 and \sigma=1)

Numbers from normal distributions with different parameters \mu and \sigma can be generated easily by passing these parameters to the constructor. For example:

boost::variate_generator<boost::mt19937, boost::normal_distribution<> >
  gen(igen,
      boost::normal_distribution<>(10,0.1));

will generate numbers from a distribution with \mu=10 and \sigma=0.1.