|
|
|
Contents
[edit]
1 Mersenne Twister¶õ? #Mersenne Twister(MT) ´Â 1996~7³â¿¡ Makoto Matsumoto¿Í Takuji Nishimura¿¡ ÀÇÇØ ¹ßÇ¥µÈ ÀÇ»ç ³¼ö »ý¼º±â¸¦ ¸»ÇÕ´Ï´Ù. MT´Â ´ÙÀ½°ú °°Àº ÀåÁ¡À» °¡Áö°í ÀÖ½À´Ï´Ù.
[edit]
2.1 ¼Ò°³ #MTÀÇ ¸ðµç ÀÌÀü ¹öÀü¿¡¼ÀÇ ÃʱâÈ ·çƾ¿¡´Â, seed»óÀÇ ÃÖ»óÀ§ ºñÆ®(most significant bit)°¡ »óÅ º¤ÅÍ(state vector)¿¡ Àß ¹Ý¿µµÇÁö ¾Ê´Â´Ù´Â ÀÛÀº ¹®Á¦Á¡ÀÌ Á¸ÀçÇÕ´Ï´Ù.
We should have noticed this when an
important caution on initializing tt800 (a small cousin of MT19937) was raised by Jeff Szuhay in the world-known random-number homepage pLab, or when Dick van Albada taught us that the older initialization scheme may yield just nearly "shifted" sequence and sent us mtRand.tgz, his nicely improved C++code (2000/5/24). The both phenomena arise from the same problem, namely that if two initial states are too near with respect to the Hamming distance, then the corresponding output sequences are close to each other.
This type of defficiency becomes very clear by a report by Martin Kretschmar , who initialized the state vector with many zeroes, or some bit-pattern. ÀÌ·¸°Ô ÇÏ¸é ³¼öÀûÀÌÁö ¾ÊÀº ºÎºÐÀº ¿À·§µ¿¾È ³²¾ÆÀÖ°Ô µË´Ï´Ù.
¿©±â ÀÌ·¯ÇÑ °áÁ¡À» ÇØ°áÇÏ´Â MT19937ÀÇ »õ·Î¿î Ç¥ÁØ ÄÚµå, mt19937ar.c(arÀº ARray¸¦ ÀǹÌÇÕ´Ï´Ù)¸¦ °Ô½ÃÇÕ´Ï´Ù. ÀÌ ÄÚµå´Â seed·Î¼ ÀÓÀÇÀÇ ±æÀÌÀÇ ¹è¿À» Çã°¡ÇÏ´Â ¶Ç´Ù¸¥ ÃʱâȺκÐÀ» Æ÷ÇÔÇϰí ÀÖ½À´Ï´Ù.
[edit]
2.2 ´Ù¿î·Îµå #
[edit]
2.3 Ãß°¡»çÇ× #
[edit]
3.1 Want a half open interval [0,1) instead of closed interval [0,1]. #In the last "return()" in the function genrand(), (double)y is divided by (unsigned long)0xffffffff, i.e. 2^32-1. If you change this to 2^32, the output is distributed in [0,1). How to construct the real constant 2^32 depends on your system, but for example
double zzz = ((double)((unsigned long) 0x80000000))*2;sets the real 2^32 into zzz. We guess there is a smarter way: let us know. A master course student Sin Tanaka at the electoric engineering department of Keio University suggested to obtain a real 2^{-32} as a real constant. The corresponding code is included on the main page.
(2002/Jan.8th added) Isaku Wada gave a nice comment on this. For [0,1], replace the last return with
return y*(1.0/4294967295.0); /* reals */and for [0,1), replace the last return with return y*(1.0/4294967296.0); /* reals: [0,1)-interval */Since most compilers compute the constant when it is compiled, so this code runs with the same speed with the standard C codes, and portability and readability are better. [edit]
3.2 Need more than 32 bits accuracy. #Concatenate two successive 32-bit integers to get a 64-bit integer.
Isaku Wada again gave us a good comment. Using integer version's genrand() twice as follows:
double random(void)
{
unsigned long a=genrand()>>5, b=genrand()>>6;
return(a*67108864.0+b)*(1.0/9007199254740992.0);
}
This gives a uniform randomnumber in [0,1) with 53-bit precision.
[edit]
3.3 To use as a random source for encryption. #The sequence is, as it is, not cryptographically secure. However, if you use an appropriate Secure Hashing Algorithm (non-invertible function compressing several words into one word), then you may use them. To be precise, in the existing encryption methods with a linear pseudorandom generator (like GFSR), to replace the generator with the large period MT is valid.
In this case, you may need more than 2^32-1 initial seeds. The initializing routine sgenrand(seed) of MT is a mere linear-congruential generator. If you do not use sgenrand, then the actual initial seed consist of the 19937 bits = the 19968 bits of the array mt0..623 minus the lower 31 bits of mt[0]. Help: we are not experts in this area. Please let us know appropriate references and knowledges on cryptographically secure generators.
[edit]
3.4 Want a uniform discrete distribution among the integers 0..N-1, e.g. a dice in the case of N=6. #If the application is not sensitive to the rounding off error, then please multiply N to [0,1)-real uniform random numbers and take the integer part (this is sufficient for most applications).
Caution: never use [0,1]-real version. If one does, then a hard-to-find bug creeps in that 0xffffffff occurs once in about 4.2 billion generations hence returns N. (Isaku Wada pointed out, added on 2002/Jan.8th.)
In the very rare case that the rounding off error of real numbers does matter, then generate random integers, take the minimum integer with N<=2^n, take the most significant n bits and discard the numbers greater than or equal to N.
[edit]
3.5 A seed of 32-bit is too small. We want a larger space for initial seeds. #Seed space of 622 words of 32-bit integers is available. For example, in mt19937.c, there is an array named mt[N]. Read the code of sgenrand(), then you will find that the seed word is passed to mt[0], and then mt[1], mt[2], ... are filled by a random number generator. You may put the value 0xffffffff to mt[0], and use all the rest mt[1]...mtN-1 as 622 words' seed space. Every initial value is safe. Some versions of mt implements the array in a converse way, so carefully read the code if you use other versions.
|
|
|||||||||