1, mt19937 实现源码
mt19937-64bit_ex.cpp
/*References:T. Nishimura, ``Tables of 64-bit Mersenne Twisters''ACM Transactions on Modeling and Computer Simulation 10. (2000) 348--357.M. Matsumoto and T. Nishimura,``Mersenne Twister: a 623-dimensionally equidistributeduniform pseudorandom number generator''ACM Transactions on Modeling and Computer Simulation 8. (Jan. 1998) 3--30.
*/#include <stdio.h>#define NN 312
#define MM 156
#define MATRIX_A 0xB5026F5AA96619E9ULL
#define UM 0xFFFFFFFF80000000ULL /* Most significant 33 bits */
#define LM 0x7FFFFFFFULL /* Least significant 31 bits *//* The array for the state vector */
static unsigned long long mt[NN];
/* mti==NN+1 means mt[NN] is not initialized */
static int mti=NN+1; /* initializes mt[NN] with a seed */
void init_genrand64(unsigned long long seed)
{mt[0] = seed;for (mti=1; mti<NN; mti++) mt[mti] = (6364136223846793005ULL * (mt[mti-1] ^ (mt[mti-1] >> 62)) + mti);
}/* initialize by an array with array-length */
/* init_key is the array for initializing keys */
/* key_length is its length */
void init_by_array64(unsigned long long init_key[],unsigned long long key_length)
{unsigned long long i, j, k;init_genrand64(19650218ULL);i=1; j=0;k = (NN>key_length ? NN : key_length);for (; k; k--) {mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 3935559000370003845ULL))+ init_key[j] + j; /* non linear */i++; j++;if (i>=NN) { mt[0] = mt[NN-1]; i=1; }if (j>=key_length) j=0;}for (k=NN-1; k; k--) {mt[i] = (mt[i] ^ ((mt[i-1] ^ (mt[i-1] >> 62)) * 2862933555777941757ULL))- i; /* non linear */i++;if (i>=NN) { mt[0] = mt[NN-1]; i=1; }}mt[0] = 1ULL << 63; /* MSB is 1; assuring non-zero initial array */
}/* generates a random number on [0, 2^64-1]-interval */
unsigned long long genrand64_int64(void)
{int i;unsigned long long x;static unsigned long long mag01[2]={0ULL, MATRIX_A};if (mti >= NN) { /* generate NN words at one time *//* if init_genrand64() has not been called, *//* a default initial seed is used */if (mti == NN+1) init_genrand64(5489ULL); for (i=0;i<NN-MM;i++) {x = (mt[i]&UM)|(mt[i+1]&LM);mt[i] = mt[i+MM] ^ (x>>1) ^ mag01[(int)(x&1ULL)];}for (;i<NN-1;i++) {x = (mt[i]&UM)|(mt[i+1]&LM);mt[i] = mt[i+(MM-NN)] ^ (x>>1) ^ mag01[(int)(x&1ULL)];}x = (mt[NN-1]&UM)|(mt[0]&LM);mt[NN-1] = mt[MM-1] ^ (x>>1) ^ mag01[(int)(x&1ULL)];mti = 0;}x = mt[mti++];x ^= (x >> 29) & 0x5555555555555555ULL;x ^= (x << 17) & 0x71D67FFFEDA60000ULL;x ^= (x << 37) & 0xFFF7EEE000000000ULL;x ^= (x >> 43);return x;
}/* generates a random number on [0, 2^63-1]-interval */
long long genrand64_int63(void)
{return (long long)(genrand64_int64() >> 1);
}/* generates a random number on [0,1]-real-interval */
double genrand64_real1(void)
{return (genrand64_int64() >> 11) * (1.0/9007199254740991.0);
}/* generates a random number on [0,1)-real-interval */
double genrand64_real2(void)
{return (genrand64_int64() >> 11) * (1.0/9007199254740992.0);
}/* generates a random number on (0,1)-real-interval */
double genrand64_real3(void)
{return ((genrand64_int64() >> 12) + 0.5) * (1.0/4503599627370496.0);
}int main(void)
{int i;unsigned long long init[4]={0x12345ULL, 0x23456ULL, 0x34567ULL, 0x45678ULL}, length=4;init_by_array64(init, length);printf("1000 outputs of genrand64_int64()\n");for (i=0; i<1000; i++) {printf("%20llu ", genrand64_int64());if (i%5==4) printf("\n");}printf("\n1000 outputs of genrand64_real2()\n");for (i=0; i<1000; i++) {printf("%10.8f ", genrand64_real2());if (i%5==4) printf("\n");}return 0;
}//http://www.math.sci.hiroshima-u.ac.jp
gcc xxx.c
2,运行效果
3, 算法原理
梅森旋转算法(Mersenne Twister Algorithm,简称 MT)是为了解决过去伪随机数发生器(Pseudo-Random Number Generator,简称 PRNG)产生的伪随机数质量不高而提出的新算法。该算法由松本眞(Makoto Matsumoto)和西村拓士(Takuji Nishimura)在 1997 年提出,期间还得到了「算法之神」高德纳(Donald Ervin Knuth)的帮助。
它被这样叫是因为周期长度是一个梅森素数。梅森素数是 2^n-1 形式的素数,因此 7 和 127 是梅森素数;当然,用在这个算法中的梅森素数更大。这个引擎的应用非常广泛,因为它可以生成非常高质量的序列,但存在速度相对较慢的缺点。这个算法很复杂并且包含很多的参数。
未完待续。。。