====== Chess - Programming - PRNG (Pseudo Random Number Generator) - Linear Congruential Generator ======
**Linear Congruential Generator** is most common and oldest algorithm for generating pseudo-randomized numbers.
The generator is defined by the recurrence relation:
Xn+1 = (aXn + c) mod c
**NOTE:** where
* **X** is the sequence of pseudo-random values.
* **m**, 0< m- modulus.
* **a**, 0< a
#include
using namespace std;
int main()
{
int M = 8;
int a = 5;
int c = 3;
int X = 1;
int i;
for(i=0; i<8; i++)
{
X = (a * X + c) % M;
std::cout << X << “ “;
}
return 0;
}
returns:
0 3 2 5 4 7 6 1
**NOTE:** This generates a sequence of numbers from 0 to 7 in a fairly scrambled way.
* If we were to extend the loop we would find that this sequence would repeat over and over.
* This sequence happens to have a period of M, but other choices for a, and c could have smaller periods (a=3, c=3 has a period of 4).
To make this more useful we will need a large period.
* To do this we have to choose appropriate values for M, a, and c.
* To have a maximum period of M the following conditions must be met:
- M and c are Relatively Prime so the gcd(M, c) = 1.
- (a-1) is divisible by all prime factors of M.
- (a-1) mod 4 = 0 if (M mod 4) = 0
----
#include
#include
static const double A = 0.001342;
static const double C = 0.00025194;
static const double RAND_MAX = 1.0;
double rand()
{
static double prev = 0;
// WRONG: prev = A * prev + fmod(C, RAND_MAX);
prev = (A * prev + C) % (RAND_MAX+1);
return prev;
}
int main(int argc, char **argv)
{
for(int i=0; i<6; i++)
std::cout << rand() << "\n";
return 0;
}
returns:
0.00025194
0.000252278
0.000252279
0.000252279
0.000252279
0.000252279
----
===== Switching to int instead of double =====
This gives some nice results:
#include
#include
static const int A = 5;
static const int C = 3;
static const int RAND_MAX = 8;
double rand()
{
static int prev = 1;
// WRONG: prev = A * prev + fmod(C, RAND_MAX);
prev = (A * prev + C) % (RAND_MAX+1);
return prev;
}
int main(int argc, char **argv)
{
for(int i=0; i<100; i++)
std::cout << rand() << "\n";
return 0;
}
returns:
8
43
218
1093
5468
27343
136718
683593
3.41797e+06
1.70898e+07
8.54492e+07
4.27246e+08
2.13623e+09
2.09122e+09
1.86615e+09
7.40836e+08
-5.90786e+08
1.34104e+09
...
----
===== References =====
https://en.wikipedia.org/wiki/Linear_congruential_generator
https://www.dreamincode.net/forums/topic/24225-random-number-generation-102/
https://medium.com/@sddkal/c-reimplementing-default-congruential-random-generator-6000936f38a3
https://codeforces.com/blog/entry/61587