RNG analysis: LCG

Source: Internet
Author: User

The old LCG (linear congruential generator) represents the best and simplest pseudo-random number generator algorithm. The main reason is that it is easy to understand, easy to implement, and fast.

 

The LCG algorithm is based on the formula:

X (n + 1) = (A * x (n) + C) % m

The coefficients are as follows:

Module M, m> 0
Coefficient A, 0 <A <m
Incremental C, 0 <= C <m
Original Value (SEED) 0 <= x (0) <m
The parameters C, M, and a are sensitive, or directly affect the quality of pseudo-random numbers.

Generally, m with a high LCG value is the exponential power of 2 (generally 2 ^ 32 or 2 ^ 64), because the modulo operation truncates the rightmost 32 or 64 bit. This theory is used in most compiler libraries to implement its pseudo-random number generator rand ().

The following are the parameter values used by some compilers:

Source m a c rand ()/random (l) <br/> numerical recipes <br/> 2 ^ 32 1664525 1013904223 <br/> Borland C/C ++ <br/> 2 ^ 32 22695477 1 bit 30.. 16 In rand (), 30 .. 0 in lrand () <br/> glibc (used by GCC) <br/> 2 ^ 32 1103515245 12345 bits 30 .. 0 <br/> ansi c: Watcom, digital Mars, codewarrior, IBM visualage C/C ++ <br/> 2 ^ 32 1103515245 12345-bit 30 .. 16 <br/> Borland Delphi, virtual Pascal <br/> 2 ^ 32 134775813 1-bit 63 .. 32 of (seed * l) <br/> Microsoft Visual/quick C/C ++ <br/> 2 ^ 32 214013 2531011 bits 30 .. 16 <br/> Apple carbonlib <br/> 2 ^ 31-1 16807 0 see Park-Miller random number generator </P> <p>

 

LCG cannot be used for scenarios with high random numbers. For example, it cannot be used for Monte Carlo simulation or encryption applications.

LCG has some serious defects. For example, if LCG is used as the point coordinate of the n-dimensional space, these points are located at most on the M1/n superplane (marsaglia theorem ), this is because of the successive Association of x (n) values.

Another problem is that if M is set to 2, the generated low sequence cycle is much smaller than the overall.
In general, the minimum N bits in Base B of the output sequence, BK = m (K is an integer), and the maximum period bn.
In some cases, LCG has good applications, such as embedded systems with tight memory. Small integers used in the e-game console can be used with high positions.

 

A c ++ implementation version of LCG is as follows:

//************************************** ******************************** <Br/> // copyright (c) 2008-2009 chipset <br/> // This program is free software: you can redistribute it and/or modify <br/> // it under the terms of the GNU affero General Public License as <br/> // published by the Free Software Foundation, either version 3 of the <br/> // license, or (at your option) any later version. <br/> // but without any warranty; without even the implied warranty of <br/> // merchantability or fitness for a participant purpose. see the <br/> // GNU affero General Public License for more details. <br/> // You shocould have stored ed a copy of the GNU affero General Public License <br/> // along with this program. if not, see <pttp://www.gnu.org/licenses/>. <br/> //********************************** ************************************ <br /># ifndef lcrandom_hpp _ <br/> # define lcrandom_hpp _ <br/> # include <ctime> </P> <p> class lcrandom <br/> {<br/> public: <br/> explicit lcrandom (size_t S = 0): seed (s) <br/>{< br/> If (0 = seed) seed = STD :: time (0); <br/> randomize (); <br/>}</P> <p> void reset (size_t S) <br/> {<br/> seed = s; <br/> If (0 = seed) seed = STD: time (0 ); <br/> randomize (); <br/>}</P> <p> size_t rand () <br/>{< br/> // returns a random integer in the range [0,-1ul) <br/> randomize (); <br/> return seed; <br/>}</P> <p> double real () <br/> {<br/> // returns a random real number in the range [0.0, 1.0) <br/> randomize (); <br/> return (double) (SEED)/-1ul; <br/>}</P> <p> PRIVATE: <br/> size_t seed; <br/> void randomize () {seed = 1103515245ul * seed + 12345ul;} <br/> }; </P> <p> class lcrand_help <br/> {<br/> static lcrandom R; <br/> Public: <br/> lcrand_help () {}< br/> void operator () (size_t s) {R. reset (s) ;}< br/> size_t operator () const {return r. rand () ;}< br/> double operator () (double) {return r. real () ;}< br/>}; <br/> lcrandom lcrand_help: R; </P> <p> extern void lcsrand (size_t s) {lcrand_help () (s) ;}< br/> extern size_t lcirand () {return lcrand_help () ;}< br/> extern double lcdrand () {return lcrand_help () (1.0) ;}</P> <p> # endif // lcrandom_hpp _

 

If you need high-quality pseudo-random numbers with sufficient memory (about 2 kb), The Mersenne Twister algorithm is a good choice. Mersenne Twister generates random numbers with a mass of almost any LCG. However, the implementation of Mersenne Twister generally uses LCG to generate seeds.

Mersenne Twister is a pseudo-random number generator developed in 1997 by Makoto Matsumoto and takuji Nishimura. It is based on Matrix linear regeneration on finite binary fields. It can quickly generate high-quality pseudo-random numbers, correcting many defects of the algorithm for generating old random numbers. The Mersenne Twister name comes from the fact that the cycle length is usually the Mersenne prime number. There are two common variants of Mersenne Twister mt19937 and Mersenne Twister MT19937-64.

Mersenne Twister has many advantages. For example, period 2 ^ 19937-1 is large enough for general applications, and the sequence Association is small. It can pass many random tests.
For more information about Mersenne Twister, see http://www.cppblog.com/Chipset/archive/2009/01/19/72330.html

Many versions of pseudo-random numbers are implemented using the Mersenne Twister algorithm. For example, the high quality and fast random number generator in the boost library is compiled using the Mersenne Twister algorithm principle.

 

The following is a C ++ Implementation of Mersenne Twister:

//************************************** ******************************** <Br/> // this is a slightly modified version of equamen Mersenne Twister. <br/> // copyright (c) 2009 chipset <br/> // This program is free software: you can redistribute it and/or modify <br/> // it under the terms of the GNU affero General Public License as <br/> // published by the Free Software Foundation, EIT Her version 3 of the <br/> // license, or (at your option) any later version. <br/> // but without any warranty; without even the implied warranty of <br/> // merchantability or fitness for a participant purpose. see the <br/> // GNU affero General Public License for more details. <br/> // You shoshould have stored ed a copy of the GNU affero General Public License <br/> // along with this PR Ogram. if not, see <pttp://www.gnu.org/licenses/>. <br/> //********************************** *********************************** </ p> <p> # ifndef mtrandom_hpp _ <br/> # define mtrandom_hpp _ </P> <p> # include <stddef. h> </P> <p> class mtrandom <br/> {<br/> Public: <br/> mtrandom (): Left (1) {Init ();} <br/> explicit mtrandom (size_t seed): Left (1) {Init (SEED) ;}< br/> mtrandom (size_t * init_key, int key_leng Th): Left (1) <br/>{< br/> int I = 1, j = 0; <br/> int K = n> key_length? N: key_length; <br/> Init (); <br/> for (; k; -- K) <br/> {<br/> State [I] = (State [I] ^ (State [I-1] ^ (State [I-1]> 30)) * 1664525ul) + init_key [J] + J; // non linear <br/> State [I] & = 4294967295ul; // For wordsize> 32 machines <br/> ++ I; ++ J; <br/> if (I> = N) <br/>{< br/> State [0] = State [n-1]; <br/> I = 1; <br/>}< br/> If (j> = key_length) <br/> J = 0; <br/>}< br/> for (k = n-1; k ;-- K) <br/> {<br/> State [I] = (State [I] ^ (State [I-1] ^ (State [I-1]> 30)) * 1566083941ul)-I; // non linear <br/> State [I] & = 4294967295ul; // For wordsize> 32 machines <br/> ++ I; <br/> if (I >= N) <br/>{< br/> State [0] = State [n-1]; <br/> I = 1; <br/>}< br/> State [0] = 2147483648ul; // MSB is 1; assuring non-zero initial array <br/>}</P> <p> void reset (size_t RS) <br/>{< br/> Init (RS); <br/> next_state (); <br/>}</P> <p> size_t rand () <br/>{< br/> size_t y; <br/> If (0 = -- left) <br/> next_state (); <br/> Y = * Next ++; <br/> // tempering <br/> y ^ = (Y> 11 ); <br/> y ^ = (Y <7) & 0x9d2c5680ul; <br/> y ^ = (Y <15) & 0xefc60000ul; <br/> y ^ = (Y> 18); <br/> return y; <br/>}</P> <p> double real () {return (double) rand ()/-1ul ;}</P> <p> // generates a random number on [0, 1) with 53-bit resolution <br/> double res53 () <br/> {<br/> size_t A = rand ()> 5, B = rand () >>6; <br/> return (A * 67108864.0 + B)/9007199254740992.0; <br/>}</P> <p> PRIVATE: <br/> void Init (size_t seed = 19650218ul) <br/> {<br/> State [0] = Seed & 4294967295ul; <br/> for (Int J = 1; j <n; ++ J) <br/> {<br/> State [J] = (1812433253ul * (State [J-1] ^ (State [J-1]> 30 )) + J); <br/> // see Knuth taocp vol2. 3rd ed. p.106 for multiplier. <br/> // In the previous versions, MSBs of the seed affect <br/> // only MSBs of the array State []. <br/> // 2002/01/09 modified by Makoto Matsumoto <br/> State [J] & = 4294967295ul; // For> 32 bit machines <br/>}</P> <p> void next_state () <br/>{< br/> size_t * P = State; <br/> int I; <br/> for (I = N-m + 1; -- I; + + p) <br/> * P = (P [m] ^ twist (P [0], p [1]); <br/> for (I = m; -- I; ++ P) <br/> * P = (P [M-N] ^ twist (P [0], p [1]); <br/> * P = P [M-N] ^ twist (P [0], State [0]); <br/> left = N; <br/> next = State; <br/>}</P> <p> size_t mixbits (size_t U, size_t V) const <br/>{< br/> return (U & 2147483648ul) | (V & 2147483647ul ); <br/>}</P> <p> size_t twist (size_t U, size_t v) const <br/>{< br/> return (mixbits (u, v)> 1) ^ (V & 1ul? 2567483615ul: 0ul); <br/>}</P> <p> static const int n = 624, M = 397; <br/> size_t State [N]; <br/> size_t left; <br/> size_t * Next; <br/> }; </P> <p> class mtrand_help <br/> {<br/> static mtrandom R; <br/> Public: <br/> mtrand_help () {}< br/> void operator () (size_t s) {R. reset (s) ;}< br/> size_t operator () const {return r. rand () ;}< br/> double operator () (double) {return r. real () ;}< br/>}; <br/> mtrandom mtrand_help: R; </P> <p> extern void mtsrand (size_t s) {mtrand_help () (s) ;}< br/> extern size_t mtirand () {return mtrand_help () ;}< br/> extern double mtdrand () {return mtrand_help () (1.0) ;}</P> <p> # endif // mtrandom_hpp _

 

(Note: Part of the content from: "generate pseudo random number two common algorithms" http://bbs.pfan.cn/post-293562.html)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.