You heard the Mersenne Twister

(Standard beginning)

If the individual Timei Sen rotation algorithm and we may very strange, but when it comes to random C ++ 11 may be more familiar to everyone. In fact, the random number C ++, python and other computer languages ​​are generated by Mersenne Twister. (Also called Mason a winding algorithm)

Well, this paper focuses on MasonspiralRotation algorithm

(Algorithm itself is very academic, I try to write light-hearted)

First here to thank @ dgklr guide Gangster. If he did not mention, I may not know the algorithm.

Introduction rotation algorithm

Mersenne Twister can also be written MT19937. There really is algorithm consists of Matsumoto and Nishimura Tinto disabilities can quickly produce high-quality random numbers In a 1997 development.

In fact, this algorithm has nothing to do with Mason, the reason why it is called the Mersenne Twister because its circulation section is 2 ^ 19937-1, this is called Mersenne primes.

If you have read my essay random number essay should know something about the pseudo-random. The reason why is this random algorithm to produce "quality", "random number, it is characterized by a particularly long cycle section. And distribution is generated by comparing the average.

Some students may be a little doubt on this cycle section. 2 ^ 19937-1 may feel a little short?

I am here to give an idea about:

10 ^ 11 stars of magnitude in the Galaxy

The number of sand in the Sahara of magnitude of 10 ^ 26

Current magnitude particles observable universe is 10 ^ 87

2 orders of magnitude is 10 ^ 19 937 ^ 6001

This comparison probably know the answer right

The difference is already more than an order of magnitude of

He also distributed in 623 dimensions are very uniform (that do not understand)

The average distribution know enough

Mason

(Mason Town House)

->continue

Pre-knowledge

Analysis of pre-knowledge of the principles of this algorithm requires online talking about are more around, I am here to look at popular science, mainly recognize these terms.

(The word is not accurate light spray)

Linear feedback shift register (LFSR)

Linear feedback shift register

This, it is when it is a random number generator to get away, do not go too tangled definitions. He will speak later.

Primitive polynomial

Simply put, that is not to simplify the polynomial

For example y = x ^ 4 + x ^ 2 can be simplified

Also know like

level

The computer unit of a binary (1 or 0) is a

This should be relatively easy to understand

Feedback function

This knowledge should be watching something else online blog about the most

简单地理解成告诉你你要对这个寄存器干什么的一个函数就好了

(看到这里应该还没懵吧)

异或

这个...

还要我科普吗?

就是两个数,如果都是0或都是1就输出0,一个1一个0输出1.

->continue

原理分析

这个旋转算法实际上是对一个19937级的二进制序列作变换。

首先我们达成一个共识:

一个长度为n的二进制序列,它的排列长度最长为2^n。

当然这个也是理论上的,实际上可能因为某些操作不当,没挺到2^n个就开始循环了。

那么如何将这个序列的排列撑满2^n个,就是这个旋转算法的精髓。

如果反馈函数的本身+1是一个本原多项式,那么它的循环节达到最长,即2^n-1

这个数学证明本文不作过多论述,有兴趣者可以自己查阅资料

个人感觉单讲知识点挺难懂的(笔者就是这么被坑的)

我们就拿一个4级的寄存器模拟一下:

我们这里使用的反馈函数是 y=x^4+x^2+x+1(这个不是本原多项式,只是拿来好理解) 这个式子中x^4,x^2,x的意思就是我们每次对这个二进制序列的从后往前数第4位和第2位做异或运算 ,然后再拿结果和最后一位做异或运算。把最后的结果放到序列的开头,整个序列后移一位,最后一位舍弃(或者输出)

first step

  1. 初始数组 { 1 , 0 , 0 , 0 } (为什么不是 0,0,0,0 你们可以自己想想,文章末尾揭晓)

The second step

  1. 将它的第四位和第二位抓出来做异或运算

third step

  1. 把刚刚的运算结果和最后一位再做一次运算

the fourth step

  1. 把最后的运算结果放到第一位,序列后移。最后一位被无情的抛弃

这就是一次运算,然后这个算法就是不断循环这几步,从而不断伪随机改变这个序列。

上图是一个网上找的一个4级寄存器的模拟过程

大家可以推一下,它所使用的反馈函数(y=x^4+x+1)

因为这个是本原多项式

所以他最后的循环节是2^4-1=15

运算结果如下:

result

(图片摘自原文链接

关于旋转

可能有人到这里还没看出“旋转”在哪里。因为我们每次计算出来的结果会放在开头,序列后移一位。看起来就像数组在向后旋转...

(Gif originally wanted to do, then do not know how to make a rotation)

All of you to make the brain

->continue

Code

(Writer is lazy, direct conveyed original code source code)

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <time.h>

using namespace std;

bool isInit;
int index;
int MT[624];  //624 * 32 - 31 = 19937

void srand(int seed)
{
    index = 0;
    isInit = 1;
    MT[0] = seed;
    for(int i=1; i<624; i++)
    {
        int t = 1812433253 * (MT[i-1] ^ (MT[i-1] >> 30)) + i;
        MT[i] = t & 0xffffffff;   //取最后的32位
    }
}

void generate()
{
    for(int i=0; i<624; i++)
    {
        // 2^31 = 0x80000000
        // 2^31-1 = 0x7fffffff
        int y = (MT[i] & 0x80000000) + (MT[(i+1) % 624] & 0x7fffffff);
        MT[i] = MT[(i + 397) % 624] ^ (y >> 1);
        if (y & 1)
            MT[i] ^= 2567483615;
    }
}
int rand()
{
    if(!isInit)
        srand((int)time(NULL));
    if(index == 0)
        generate();
    int y = MT[index];
    y = y ^ (y >> 11);
    y = y ^ ((y << 7) & 2636928640);
    y = y ^ ((y << 15) & 4022730752);
    y = y ^ (y >> 18);
    index = (index + 1) % 624;
    return y;  //笔者注:y即为产生的随机数 
}

int main()
{
    srand(0);  //设置随机种子
    int cnt = 0;
    for(int i=0; i<1000000; i++)  //下面的循环是用来判断随机数的奇偶概率的 
    {
        if(rand() & 1)
            cnt++;
    }
    cout<<cnt / 10000.0<<"%"<<endl;
    return 0;
}

->continue

Fill out the front of the pit

Here to answer the previous question:

Why loop section is 2 ^ n-1 instead of 2 ^ n

And why the answer to this question can not be the initial sequence is {0, 0, 0, 0} is the same as if the whole is 0, then, no matter how exclusive-or operation can not produce cycle. So also how pseudo-random ah.

Because not all 0s, the loop section to -1

(* O *)

(A ⊕ ⊕)

Finally, thank you very much to have the patience to read here.

We are strong, we can encourage each other with them.

Guess you like

Origin www.cnblogs.com/CHNmuxii/p/12232475.html