(標準の始まり)
個々Timeiセン回転アルゴリズムであれば、我々は非常に奇妙かもしれないが、それはランダムなC ++ 11になると誰にでも馴染みかもしれません。実際には、乱数C ++、Pythonと他のコンピュータ言語は、メルセンヌツイスターによって生成されます。(また、巻アルゴリズムメイソンと呼ばれます)
さて、本論文ではメイソンに焦点を当ててスパイラル回転アルゴリズム
(アルゴリズム自体は非常に学術的ですが、私は快活なを書いてみます)
まずここでは、@感謝するdgklrガイドギャング。彼は言及しなかった場合、私はアルゴリズムを知らないかもしれません。
はじめに回転アルゴリズム
メルセンヌツイスターもMT19937書き込むことができます。本当にアルゴリズムはすぐに1997の開発では、高品質な乱数を生成することができ松本と西村ティント障害者で構成されてあります。
実際には、このアルゴリズムはメイソン、その循環部は、2 ^ 19937から1であるので、それはメルセンヌツイスターと呼ばれる理由、これと呼ばれているメルセンヌ素数とは何の関係もありません。
あなたは私のエッセイ乱数エッセイを読んでいれば、擬似ランダムについて何かを知っている必要があります。この農産物「品質」にランダムアルゴリズム、「乱数である理由は、それが特に長いサイクル部を特徴とする。そして、分布は平均値を比較することによって生成されます。
一部の学生は、このサイクル部分に少し疑問かもしれません。2 ^ 19937から1には少し短いを感じること?
私は約アイデアを与えるためにここにいます:
銀河における大きさの10 ^ 11星
10 ^ 26の大きさのサハラの砂の数
観測可能な宇宙は10 ^ 87で電流の大きさの粒子
2桁は10 ^ 19 937 ^ 6001であります
この比較は、おそらくその答えの権利を知っています
違いは程度の大きさよりも、すでに多くのです
彼はまた、(理解していないこと)623次元で非常に均一である分散します
平均分布のノウハウを十分に
(メイソンタウンハウス)
- >続けます
事前知識
このアルゴリズムの原則の事前知識の分析は、オンラインで、私は主にこれらの用語を認識し、人気の科学を見てここにいる、より多くの周りは約話をする必要があります。
(ワードは、正確な光スプレーではありません)
リニアフィードバックシフトレジスタ(LFSR)
これは、それが離れて取得する乱数生成器であるとき、あまりにももつれ定義を行っていないです。彼は後に話します。
原始多項式
簡単に言えば、それは多項式を簡素化することではありません
例えば、Y = X ^ 4 + X ^ 2を簡略化することができます
また、同様に知っています
レベル
バイナリ(1又は0)のコンピュータユニットは、aは
これは比較的理解しやすいはずです
フィードバック機能
この知識は、ほとんどについてのブログ、オンラインで何かを見てする必要があります
简单地理解成告诉你你要对这个寄存器干什么的一个函数就好了
(看到这里应该还没懵吧)
异或
这个...
还要我科普吗?
就是两个数,如果都是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位做异或运算 ,然后再拿结果和最后一位做异或运算。把最后的结果放到序列的开头,整个序列后移一位,最后一位舍弃(或者输出)
- 初始数组 { 1 , 0 , 0 , 0 } (为什么不是 0,0,0,0 你们可以自己想想,文章末尾揭晓)
- 将它的第四位和第二位抓出来做异或运算
- 把刚刚的运算结果和最后一位再做一次运算
- 把最后的运算结果放到第一位,序列后移。最后一位被无情的抛弃
这就是一次运算,然后这个算法就是不断循环这几步,从而不断伪随机改变这个序列。
上图是一个网上找的一个4级寄存器的模拟过程
大家可以推一下,它所使用的反馈函数(y=x^4+x+1)
因为这个是本原多项式
所以他最后的循环节是2^4-1=15
运算结果如下:
(图片摘自原文链接)
关于旋转
可能有人到这里还没看出“旋转”在哪里。因为我们每次计算出来的结果会放在开头,序列后移一位。看起来就像数组在向后旋转...
(GIFはもともとやってみたかった、そして回転を作る方法がわかりません)
脳を作るために、あなたのすべて
- >続けます
コードの実装
(ライター遅延、直接搬送され、元のコードのソースコード)
#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;
}
- >続けます
ピット前を記入
ここでは、前の質問に答えるために:
なぜループ部は、2 ^ n-1個の代わりに2 ^ nは
この質問に対する答えは、最初の配列であることができない理由と、{0、0、0、0}は、全体が、その後、サイクルを生成することはできませんどのように排他的論理和演算に関係なく0である場合と同じです。だから、また、どのように擬似ランダムああ。
すべてではない0そのため、ループ部に-1
(* O *)
(A⊕⊕)
最後に、ここで読むために忍耐を持っていることは非常にありがとうございました。
我々は彼らとお互いを奨励することができ、強いです。