[c++] How do you generate a random double uniformly distributed between 0 and 1 from C++?

How do you generate a random double uniformly distributed between 0 and 1 from C++?

Of course I can think of some answers, but I'd like to know what the standard practice is, to have:

  • Good standards compliance
  • Good randomness
  • Good speed

(speed is more important than randomness for my application).

Thanks a lot!

PS: In case that matters, my target platforms are Linux and Windows.

This question is related to c++ random

The answer is


Well considering simplicity and speed as your primary criteria, you can add a small generic helper like this :-

  // C++ rand generates random numbers between 0 and RAND_MAX. This is quite a big range
  // Normally one would want the generated random number within a range to be really
  // useful. So the arguments have default values which can be overridden by the caller
  int nextRandomNum(int low = 0, int high = 100) const {
    int range = (high - low) + 1;
    // this modulo operation does not generate a truly uniformly distributed random number
    // in the span (since in most cases lower numbers are slightly more likely), 
    // but it is generally a good approximation for short spans. Use it if essential
    //int res = ( std::rand() % high + low );
    int res = low + static_cast<int>( ( range * std::rand() / ( RAND_MAX + 1.0) ) );
    return res;
  }

Random number generation is a well studied, complex and advanced topic. You can find some simple but useful algorithms here apart from the ones mentioned in other answers:-

Eternally Confuzzled


If speed is your primary concern, then I'd simply go with

double r = (double)rand() / (double)RAND_MAX;

As I see it, there are three ways to go with this,

1) The easy way.

double rand_easy(void)
{       return (double) rand() / (RAND_MAX + 1.0);
}

2) The safe way (standard conforming).

double rand_safe(void)
{
        double limit = pow(2.0, DBL_MANT_DIG);
        double denom = RAND_MAX + 1.0;
        double denom_to_k = 1.0;
        double numer = 0.0;

        for ( ; denom_to_k < limit; denom_to_k *= denom )
           numer += rand() * denom_to_k;

        double result = numer / denom_to_k;
        if (result == 1.0)
           result -= DBL_EPSILON/2;
        assert(result != 1.0);
        return result;
}

3) The custom way.

By eliminating rand() we no longer have to worry about the idiosyncrasies of any particular version, which gives us more leeway in our own implementation.

Note: Period of the generator used here is ≅ 1.8e+19.

#define RANDMAX (-1ULL)
uint64_t custom_lcg(uint_fast64_t* next)
{       return *next = *next * 2862933555777941757ULL + 3037000493ULL;
}

uint_fast64_t internal_next;
void seed_fast(uint64_t seed)
{       internal_next = seed;
}

double rand_fast(void)
{
#define SHR_BIT (64 - (DBL_MANT_DIG-1))
        union {
            double f; uint64_t i;
        } u;
        u.f = 1.0;
        u.i = u.i | (custom_lcg(&internal_next) >> SHR_BIT);
        return u.f - 1.0;
}

Whatever the choice, functionality may be extended as follows,

double rand_dist(double min, double max)
{       return rand_fast() * (max - min) + min;
}

double rand_open(void)
{       return rand_dist(DBL_EPSILON, 1.0);
}

double rand_closed(void)
{       return rand_dist(0.0, 1.0 + DBL_EPSILON);
}

Final notes: The fast version - while written in C - may be adapted for use in C++ to be used as a replacement for std::generate_canonical, and will work for any generator emitting values with sufficient significant bits.

Most 64 bit generators take advantage of their full width, so this can likely be used without modification (shift adjustment). e.g. this works as-is with the std::mt19937_64 engine.


An old school solution like:

double X=((double)rand()/(double)RAND_MAX);

Should meet all your criteria (portable, standard and fast). obviously the random number generated has to be seeded the standard procedure is something like:

srand((unsigned)time(NULL));

The C++11 standard library contains a decent framework and a couple of serviceable generators, which is perfectly sufficient for homework assignments and off-the-cuff use.

However, for production-grade code you should know exactly what the specific properties of the various generators are before you use them, since all of them have their caveats. Also, none of them passes standard tests for PRNGs like TestU01, except for the ranlux generators if used with a generous luxury factor.

If you want solid, repeatable results then you have to bring your own generator.

If you want portability then you have to bring your own generator.

If you can live with restricted portability then you can use boost, or the C++11 framework in conjunction with your own generator(s).

More detail - including code for a simple yet fast generator of excellent quality and copious links - can be found in my answers to similar topics:

For professional uniform floating-point deviates there are two more issues to consider:

  • open vs. half-open vs. closed range, i.e. (0,1), [0, 1) or [0,1]
  • method of conversion from integral to floating-point (precision, speed)

Both are actually two sides of the same coin, as the method of conversion takes care of the inclusion/exclusion of 0 and 1. Here are three different methods for the half-open interval:

// exact values computed with bc

#define POW2_M32   2.3283064365386962890625e-010
#define POW2_M64   5.421010862427522170037264004349e-020

double random_double_a ()
{
   double lo = random_uint32() * POW2_M64;
   return lo + random_uint32() * POW2_M32;
}

double random_double_b ()
{
   return random_uint64() * POW2_M64;
}

double random_double_c ()
{
   return int64_t(random_uint64()) * POW2_M64 + 0.5;
}

(random_uint32() and random_uint64() are placeholders for your actual functions and would normally be passed as template parameters)

Method a demonstrates how to create a uniform deviate that is not biassed by excess precision for lower values; the code for 64-bit is not shown because it is simpler and just involves masking off 11 bits. The distribution is uniform for all functions but without this trick there would be more different values in the area closer to 0 than elsewhere (finer grid spacing due to the varying ulp).

Method c shows how to get a uniform deviate faster on certain popular platforms where the FPU knows only a signed 64-bit integral type. What you see most often is method b but there the compiler has to generate lots of extra code under the hood to preserve the unsigned semantics.

Mix and match these principles to create your own tailored solution.

All this is explained in Jürgen Doornik's excellent paper Conversion of High-Period Random Numbers to Floating Point.


This is what I ended up using for my needs:

int range_upper_bound = 12345;
int random_number =((double)rand()/(double)range_upper_bound);

First include stdlib.h

#include<stdlib.h>

Then following can be a function to generate random double number between a range in C programming language.

double randomDouble() {
    double lowerRange = 1.0;
    double upperRange = 10.0;
    return ((double)rand() * (upperRange - lowerRange)) / (double)RAND_MAX + lowerRange;
}

Here RAND_MAX is defined in stdlib.h


Here's how you'd do it if you were using C++ TR1.


You could try the Mersenne Twister algorithm.

http://en.wikipedia.org/wiki/Mersenne_twister

It has a good blend of speed and randomness, and a GPL implementation.


double randDouble()
{
  double out;
  out = (double)rand()/(RAND_MAX + 1); //each iteration produces a number in [0, 1)
  out = (rand() + out)/RAND_MAX;
  out = (rand() + out)/RAND_MAX;
  out = (rand() + out)/RAND_MAX;
  out = (rand() + out)/RAND_MAX;
  out = (rand() + out)/RAND_MAX;

  return out;
}

Not quite as fast as double X=((double)rand()/(double)RAND_MAX);, but with better distribution. That algorithm gives only RAND_MAX evenly spaced choice of return values; this one gives RANDMAX^6, so its distribution is limited only by the precision of double.

If you want a long double just add a few iterations. If you want a number in [0, 1] rather than [0, 1) just make line 4 read out = (double)rand()/(RAND_MAX);.


//Returns a random number in the range (0.0f, 1.0f).
// 0111 1111 1111 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000
// seee eeee eeee vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv vvvv
// sign     = 's'
// exponent = 'e'
// value    = 'v'
double DoubleRand() {
  typedef unsigned long long uint64;
  uint64 ret = 0;
  for (int i = 0; i < 13; i++) {
     ret |= ((uint64) (rand() % 16) << i * 4);
  }
  if (ret == 0) {
    return rand() % 2 ? 1.0f : 0.0f;
  }
  uint64 retb = ret;
  unsigned int exp = 0x3ff;
  retb = ret | ((uint64) exp << 52);
  double *tmp = (double*) &retb;
  double retval = *tmp;
  while (retval > 1.0f || retval < 0.0f) {
    retval = *(tmp = (double*) &(retb = ret | ((uint64) (exp--) << 52)));
  }
  if (rand() % 2) {
    retval -= 0.5f;
  }
  return retval;
}

This should do the trick, I used this Wikipedia article to help create this. I believe it to be as good as drand48();


The random_real class from the Boost random library is what you need.