Class min_rand provides a simple-to-use C++ pseudo-random number generator based on the minimal standard random number generator described in:
"Random Number Generators; Good ones are hard to find", Stephen K. Park and Keith W. Miller, Communications of the ACM", October, 1988, Volume 31, Number 10, page 1192-1201.
The specification for class min_rand requires the use of that specific generator as a way to assure quality. Pseudo-random numbers are generated in the range 1 to 2,147,483,647 with a period one less than the range maximum, using the so-called Lehmer technique.
Class min_rand meets certain design specifications:
- Uses a specific, well-known, widely published, and peer-reviewed random number generation algorithm. The benefits include portable, repeatable, reliable, and well-known performance. Some or all of these attributes are lacking in random number generators which specify only interface without specifying methodology.
- Satisfies the requirements for a C++ Standard Library RandomNumberGenerator function object. The benefit is that min_rand can be used with any Standard Template Library (STL) compliant algorithm which requires a RandomNumberGenerator function object, including std:random_shuffle.
- Satisfies the requirements for a C++ Standard Library Generator function object. The benefit is that min_rand can be used with any Standard Template Library (STL) compliant algorithm which requires a Generator function object, including std:generate and std:generate_n.
- Can be used as a regular C++ object. The interface includes generally useful functions beyond those required solely for use as a function object. The benefit is that one class does two jobs; it is usable immediately as both a stand-alone class and as a function object.
- No coupling to any other libraries; <cassert> is the only included header. The benefits are greater portability and reduced maintenance.
- Testable, with a member returning the known-to-be-correct 10,000th value in a particular random number sequence. Benefit is greater assurance of correct operation, particularly after porting to a new environment.
- Simple enough that all code can be inline. Benefit is very fast operation.
Steve Park provided C source code written by him and Dave Geyer for study in designing min_rand. Comments in that code explain that the previous minimal standard multiplier of 16807 was changed to 48271 on 7 July 1990. Thanks, Steve.
Mats Henricson provided a trial implementation of the random number generation classes he proposed in 1993 for inclusion in the C++ Standard Library. Thanks Mats. It turned out that his implementation also used Park and Miller's minimal standard generator.
I chose to design a new interface from scratch. All mistakes in min_rand are my own.
The interface and implementation are both supplied by the header file min_rand.h.
The min_rand_test.cpp test program uses the Standard C++ assert mechanism to detect various errors. It has been compiled and run without error with the following C++ compilers:
- gcc version egcs-2.93.05 19990207 (gcc2 ss-980929 experimental) on a Sun
- Intel/EDG C++ 3.0 on a Pentium Pro
- Microsoft VC++ 5.0 with service pack 3 on a Pentium Pro
- Microsoft VC++ 6.0 with service pack 2 on a Pentium III
A test (not included) has also been run using 64-bit arithmetic, and that version of the test program also ran without error.
namespace boost { class min_rand { enum constants { modulus = 2147483647L, multiplier = 48271L, q = modulus / multiplier, r = modulus % multiplier }; long value; public: typedef long argument_type; typedef long result_type; explicit min_rand( long seed_value=1 ); min_rand& operator=( long new_value ); operator long() const; double fvalue() const; long operator++(); long operator++(int); long operator()(); long operator()( long n ); long ten_thousandth() const; }; } // namespace boost
As do the C and C++ Standards, min_rand requires that long be able to hold values from -2147483647 to +2147483647.
The compiler generates the proper copy constructor, copy assignment, and destructor; they are not described further.
The invariant (value > 0 && value <= modulus) must be maintained. All non-const member functions assert this invariant.
typedef long argument_type; typedef long result_type;
Conforms to C++ Standard Library RandomNumberGenerator and Generator function object requirement.
explicit min_rand( long seed_value=1 );
Sets value to seed_value.
min_rand& operator=( long new_value );
Sets value to new_value. Returns *this.
operator long() const;
Returns value.
double fvalue() const;
Returns double(value) / modulus.
This has the effect of returning a double > 0.0 and <= 1.0.
long operator++();
Sets value to the next number in the sequence as if by:
value = multiplier*(value%q) - r*(value/q); if ( value <= 0 ) value += modulus;Returns value after computation of the next number in the sequence.
long operator++(int);
Sets value to the next number in the sequence as if by calling operator++(). Returns value prior to computation of the next number in the sequence.
long operator()();
Returns operator++()
Conforms to C++ Standard Library Generator function object requirement.
long operator()( long n );
Returns operator++() % n
Conforms to C++ Standard Library RandomNumberGenerator function object requirement.
long ten_thousandth() const;
Returns the correct value of value after 10,000 calls to operator++() after value == 1.
The generate_n_test.cpp sample program uses the C++ Standard Library generate_n algorithm to fill a vector with 6 random numbers generated by min_rand:
It produces the output:
48271 182605794 1291394886 1914720637 2078669041 407355683
Revised 27 July 2000
© Copyright Beman Dawes 1998. Permission to copy, use, modify, sell and distribute this document is granted provided this copyright notice appears in all copies. This software is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.