The linear congruential generator is a very simple example of a random number generator. All linear congruential generators use this formula:

Where:

*r*_{0}is a seed.*r*_{1},*r*_{2},*r*_{3}, …, are the random numbers.*a*,*c*,*m*are constants.

If one chooses the values of *a*, *c* and *m* with care, then the generator produces a uniform distribution of integers from 0 to *m* − 1.

LCG numbers have poor quality. *r*_{n} and *r*_{n + 1} are not independent, as true random numbers would be. Anyone who knows *r*_{n} can predict *r*_{n + 1}, therefore LCG is not cryptographically secure. The LCG is still good enough for simple tasks like Miller-Rabin primality test, or FreeCell deals. Among the benefits of the LCG, one can easily reproduce a sequence of numbers, from the same *r*_{0}. One can also reproduce such sequence with a different programming language, because the formula is so simple.

The task is to replicate two historic random number generators. One is the `rand()`

function from BSD libc, and the other is the `rand()`

function from the Microsoft C Runtime (MSCVRT.DLL). Each replica must yield the same sequence of integers as the original generator, when starting from the same seed.

In these formulas, the seed becomes *s**t**a**t**e*_{0}. The random sequence is *r**a**n**d*_{1}, *r**a**n**d*_{2} and so on.

BSD formula:

*r**a**n**d*_{n}=*s**t**a**t**e*_{n}*r**a**n**d*_{n}is in range 0 to 2147483647.

Microsoft formula:

*r**a**n**d*_{n}is in range 0 to 32767.

#include <iostream> //-------------------------------------------------------------------------------------------------- using namespace std; //-------------------------------------------------------------------------------------------------- class mRND { public: void seed( unsigned int s ) { _seed = s; } protected: mRND() : _seed( 0 ), _a( 0 ), _c( 0 ), _m( 2147483648 ) {} int rnd() { return( _seed = ( _a * _seed + _c ) % _m ); } int _a, _c; unsigned int _m, _seed; }; //-------------------------------------------------------------------------------------------------- class MS_RND : public mRND { public: MS_RND() { _a = 214013; _c = 2531011; } int rnd() { return mRND::rnd() >> 16; } }; //-------------------------------------------------------------------------------------------------- class BSD_RND : public mRND { public: BSD_RND() { _a = 1103515245; _c = 12345; } int rnd() { return mRND::rnd(); } }; //-------------------------------------------------------------------------------------------------- int main( int argc, char* argv[] ) { BSD_RND bsd_rnd; MS_RND ms_rnd; cout << "MS RAND:" << endl << "========" << endl; for( int x = 0; x < 10; x++ ) cout << ms_rnd.rnd() << endl; cout << endl << "BSD RAND:" << endl << "=========" << endl; for( int x = 0; x < 10; x++ ) cout << bsd_rnd.rnd() << endl; cout << endl << endl; system( "pause" ); return 0; } //--------------------------------------------------------------------------------------------------

Output:

MS RAND: ======== 38 7719 21238 2437 8855 11797 8365 32285 10450 30612 BSD RAND: ========= 12345 1406932606 654583775 1449466924 229283573 1109335178 1051550459 1293799192 794471793 551188310

Content is available under GNU Free Documentation License 1.2.