Random number generators

The C++ standard is not strict about how good the random number generator rand() has to be. On Windows, it is pretty feeble, for example, its maximum value is only 32767 (= the constant MAX_RAND). The equivalent function on other systems like Linux is much better.

Here is a better generator that will give either random integers in the full range 0-4000000000ish, or random floating-point numbers in the range 0.0 to 1.0, or random integers in a range that you can specify (ah!).

It is not the best of random number generators (see Numerical Recipes in the reference section, and the mathematical part of the project ideas page for discussion). However, it is easy to cut and paste for use in your own program:

// ranqd1.cpp  quick and dirty random generator given in 
// Press et al. "Numerical Recipes in C", relies on 32-bit
// arithmetic.

// They say it should go...
// 00000000, 3C6EF35F, 47502932, D1CCF6E9, AAF95334, 6252E503,
// 9F2EC686, 57FE6C2D, A3D95FA8, 81FDBEE7, 94F0AF1A, CBF633B1

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <algorithm>

//               ---------Snip-------------    
// Random number generator.  First create an instance (use
// time(0) as a seed to get an unpredictable random sequence).
// Then use its range(lo,hi) method to get random integers in
// the  inclusive range indicated.  Alternatively, next()
// will give unsigned integers covering the full range, and
// dbl() yields random doubles (with float precision) in the
// range 0.0 to 1.0      
// This generator works on 32-bit hardware only, see Press
// et al, Numerical Recipes.
class Qdrand {
    private:
         unsigned int i;
    public:
        Qdrand(int seed=0) : i(seed) {}
        unsigned int next() {return (i=1664525L*i+1013904223L);}
    int range(int lo, int hi){ return int(lo+dbl()*(hi-lo+1));}  
    double dbl(){
        unsigned int t = 0x3f800000|(next()&0x007fffff);
        return (*(float*)&t)-1.0;
    }
};
//               --------Snip-------------    


int main() {
    // make a random generator, default initialisation 
    Qdrand r1;
    
    cout << "First six random unsigned ints =" << endl;
    for(int i=0; i<6; i++) {
    cout << hex << r1.next() << dec << "  ";
    }
    cout << endl << endl;
    
    const int NRAND= 1000000;
    const int NBINS=12;
    cout << "Stats on " << NRAND << " ints in range 2, 10" << endl;
 
    vector<int>bins(NBINS,0);
    
    for (int i=0; i<NRAND; i++) {
        bins[r1.range(2,10)]++;
    }
    
    int scale = *max_element(bins.begin(), bins.end());
    
    for (int i=0; i<NBINS; i++) {
        cout << setw(4) << i << "| "
         << string(bins[i]*50/scale,'*') << "  " << bins[i]<< endl;
    }
    cout << endl;
    cout << "size char " << sizeof(char) << endl; 
    cout << "size short " << sizeof(short) << endl; 
    cout << "size int " << sizeof(int) << endl;
    cout << "size long " << sizeof(long) << endl;   
    cout << "size float " << sizeof(float) << endl;
    cout << "size double " << sizeof(double) << endl;
    
    cout << "This generator relies on sizeof(float)==sizeof(int)==4" << endl;
    
}

Mark Colclough 24 Oct 2003