Mersenne Twistor

The 32-bit Mersenne Twistor algorithm provides a high-quality random number generator suitable for scientific applications (especially Monte Carlo). Nearby elements of the sequence it generates are very weakly correlated; all the bits in each output word are roughly equally random; and the period is incredibly large. This generator is available in the C++ standard library:

#include <random>
using std::mt19937;
using std::uniform_real_distribution;
using std::uniform_int_distribution;

static mt19937 rng; // mersenne twistor random number generator
static auto rnd = bind(uniform_real_distribution<double>(0,1),std::ref(rng)); // random number drawn uniformly from [0,1)
static auto rnd_die = bind(uniform_int_distribution<int>(1,6),std::ref(rng)); // random number drawn uniformly from {1,2,3,4,5,6}

Seeding the generator

If what you want is a pseudo-random sequence but one that is reproducible each time the program is run (which may be appropriate for debugging), you can simple specify a constant seed value.

rng.seed(1975);

However, the complete internal state of the 32-bit Mersenne Twistor random number generator is specified by 624 words. Specifying those numbers uniquely determines the current state of the generator and all its future output. The best way to seed the generator is to fill it with 624 numbers based on a high-entropy source (e.g., the random_device provided by the operating system) the first time you use it but otherwise to read in and then save the internal state at every invocation of the program:

void init_random()
{
   // This function tries to load the previous saved state of the the random number generator. 
   // Otherwise it seeds the generator from a non-deterministic source.
   // Call this function at the start of the program.
   ifstream frand("mtrand_internal_state.dat");
   if (frand.is_open())
      frand >> rng;
   else
   {
      std::array<int,624> seed_data;
      std::random_device r;
      std::generate_n(seed_data.data(), seed_data.size(), std::ref(r));
      std::seed_seq seq(std::begin(seed_data), std::end(seed_data));
      rng.seed(seq);
   }
   frand.close();
}

void save_random(void)
{
   // This function saves internal state of the random number generator.
   // Call it just before the program terminates.
   ofstream frand("mtrand_internal_state.dat");
   if (frand.is_open())
      frand << rng;
   frand.close();
}