RR: Basic random number generation

Many, many codes and books use the standard C function rand() to generate uniformly distributed random numbers. What are the potential pitfalls of using this function? What are the alternatives?

Pitfalls of rand()

There are probably quite a few, but here are a couple that come to mind first:

  • Precision: the number of random bits returned by rand() could be as low as 15 on some platforms. On GNU libc it is 31 bits. You can figure out the number on your platform from the constant RAND_MAX; most people however only every use RAND_MAX to normalise their random numbers and never check the precision.

  • Multi-thread safety: rand() is not designed for multi-threaded programs, hence it should never be used in libraries and programs of significant size/expected lifetime.

    In particular, in multi-threaded programs the sequence of numbers returned by rand() is not reproducable. This is because this function has a global state shared by the entire process (think static and global variables, would you use those?).

Alternative

If you are writing C++, I recommend using the Boost random number library (see Boost.Random), which will also be contained in the forthcoming revised C++ standard (AKA TR1).

Here is a very minimal example program of how to use this library:

// Bojan Nikolic <bojan@bnikolic.co.uk>
// Print some random numbers generated with boost

#include <iostream>
#include <boost/random.hpp>
#include <boost/format.hpp>

void printRN(size_t n)
{
  boost::mt19937 rng(43);
  for (size_t i = 0 ; i < n; ++i)
  {
    std::cout<<boost::format("A random number %i ") % rng()
          <<std::endl;
  }
}

int main(void)
{
  printRN(10);
}

Summary

If you are using C++, avoid using rand() and instead use boost or some specialised random number generation library.

(Shameless plug: I do work on customised libraries for, among other things, very fast generation of random numbers. Feel free to get in touch you are interested.)

Update 3/12/2008

The following short program illustrates how to generate uniform random numbers in interval 0 to 1:

// Bojan Nikolic <bojan@bnikolic.co.uk>
// Print uniform random numbers in (0,1) interval generated with boost

#include <iostream>
#include <boost/random.hpp>
#include <boost/format.hpp>

/// Print n random numbers in interval 0 to 1. Note that the seed is
/// always set at 43, so the sequence of numbers is always the same
void printU01(size_t n)
{
  boost::mt19937 rng(43);
  boost::uniform_01<boost::mt19937>  zeroone(rng);
  for (size_t i = 0 ; i < n; ++i)
  {
    std::cout<<boost::format("A random number %f ") % zeroone()
         <<std::endl;
  }
}

int main(void)
{
  printU01(10);
}

Note that boost::uniform_01 makes its own copy of the underlying integer generator, so the state of rng is de-coupled entirely from zeroone in the above example.