rand

rand and srand are standard library functions that provide a primitive implementation of a pseudorandom number generator (PRNG).

= API =


 * void srand(unsigned int seed) : resets the PRNG to generate a sequence of pseudorandom integers based on the given seed value. C++ uses an initial seed value of 1.


 * int rand : returns the next value in the sequence. Each value n falls in the range 0 <= n <= RAND_MAX.


 * RAND_MAX : a number in the range 32767 <= RAND_MAX <= INT_MAX (2147483647 for 32-bit integers).

= Common uses =

Range surjection
...or, in English, how to get a random number within a particular range:

inline double random(double lo, double hi, bool inclusive = false) { const double range = (inclusive ? RAND_MAX : 1.0 + RAND_MAX); return lo + rand * (hi - lo) / range; }

inline int random(int lo, int hi, bool inclusive = false) { // note: floor really only needed if hi < 0 return int(floor(random(double(lo), double(hi), inclusive))); }

Math.random
Java class java.lang.Math has a method random</tt> that returns a floating-point number n</tt> in the range 0 <= n < 1</tt>, which you can then multiply in order to get your desired range. To accomplish the same in C++:

namespace Math { inline double random { return rand / (1.0 + RAND_MAX); } }

double n; n = Math::random * 42;         // 0.0 <= n < 42.0 n = Math::random * 43;         // 0.0 <= n < 43.0 n = Math::random * 42 + 1;     // 1.0 <= n < 43.0

n = int(Math::random * 42);    // 0 <= n <= 41 n = int(Math::random * 43);    // 0 <= n <= 42 n = int(Math::random * 42) + 1; // 1 <= n <= 42

= Common problems =

Same/similar sequence of values for each run
Each call to srand(seed)</tt> starts a new sequence of pseudorandom numbers based on the given seed value. With that in mind:


 * Call it at least once per program, usually in your main</tt> function.


 * Don't call it each time you call rand</tt> or else you may get the same "random" number each time.


 * Use a unique seed value for each sequence. The entropy (randomness) of the sequence depends on the entropy of the seed.


 * Beware of using time(NULL)</tt> as your seed value. If you call time(NULL)</tt> several times in a short period, you may get the same value (or similar values), which will generate the same sequence (or similar sequences). To increase entropy, you may wish to use a seed whose value changes more frequently, such as the current process ID (Unix getpid</tt>, Windows GetCurrentProcessId</tt>) or the current time in milliseconds or nanoseconds (e.g. Unix gettimeofday</tt>, Windows GetTickCount</tt>). You can even XOR these together (e.g. time(NULL) ^ getpid</tt>).
 * As a special case, if the values can be close but never identical, you can use srand((time(0) << 16) | (time(0) >> 16))</tt> as a workaround.

Sequences don't seem to be uniformly distributed
rand</tt> may be biased in some C++ implementations. Some numbers are more likely than others to be returned.

rand % N</tt> performs poorly if <tt>rand</tt> is biased! Here's a good example:

using namespace std;
 * 1) include
 * 2) include
 * 3) include

int main { srand(time(NULL)); const int range = 1400000000; int lo = 0, hi = 0; for (int i = 0, j = 1 << 20; i < j; ++i) { if ((rand % range) < (range / 2)) { ++lo; } else { ++hi; } }  cout << "lo=" << lo << "/hi=" << hi << '\n'; }

It usually prints something like <tt>lo=684268/hi=364308</tt>, i.e. numbers are twice as likely to be in the low half of the range!

You can compensate by converting to a floating-point number and then translating it into your desired range:

int n; n = int(double(rand) * N / RAND_MAX);      // 0 <= n <= N n = int(double(rand) * N / (RAND_MAX + 1)); // 0 <= n < N

If, in the above example, we use this if-statement...

if (rand * double(range) / RAND_MAX < (range / 2)) {

...we get a more reasonable result like <tt>lo=523957/hi=524619</tt>, closer to 50/50.

Ranges approaching <tt>RAND_MAX</tt> are more susceptible to bias; and integer ranges larger than <tt>RAND_MAX</tt> cannot be completely mapped to the range of <tt>rand</tt>. If these become problems for you, you may have to look into other PRNGs, such as Boost.Random.

= See also =


 * Boost.Random provides a collection of far better PRNG implementations; apparently now part of C++ TR1
 * How can I get random integers in a certain range? (comp.lang.c FAQ)
 * HotBits: Genuine random numbers, generated by radioactive decay
 * a PRNG that exploits "randomness in the drift between the processor clock and the rate at which interval timer interrupts occur"