看到了 CSDN一位童鞋的一篇关于C11随机数的文章,才知道自己out了。之前都是用Rand来伪随机;
C11这个东东的产生随机数的原理是神马呢?二话不说,先来真相:
#include <iostream>
#include <unordered_map>
#include <random>
#include <time.h>
using namespace std;
int main()
{
std::default_random_engine generator(time(0));
std::uniform_int_distribution<int> distribution(0,100);
int i = 100;
while(i--){
int n = distribution(generator);
printf("%d\n", n);
}
}
就这样产生了0-100内的随机数,但是不知道的原理的coder不是好coder,如何知道?源码之下,了无秘密(侯捷老师对我影响是多大啊)!
下面就来看下VS2010下的实现:
通过下面的追踪可以看到:
using tr1::default_random_engine;
typedef mt19937 default_random_engine;
typedef mersenne_twister<unsigned long, 32, 624, 397, 31, 0x9908b0df,
11, 7, 0x9d2c5680, 15, 0xefc60000, 18> mt19937;
mersenne_twister原来是梅森旋转算法:(下面全文引用维基百科的解释):
梅森旋转算法(Mersenne twister)是一个伪随机数发生算法。由松本真和西村拓士[1]在1997年开发,基于有限二进制字段上的矩阵线性递归。可以快速产生高质量的伪随机数, 修正了古典随机数发生算法的很多缺陷。
Mersenne Twister这个名字来自周期长度取自梅森素数的这样一个事实。这个算法通常使用两个相近的变体,不同之处在于使用了不同的梅森素数。一个更新的和更常用的是MT19937, 32位字长。 还有一个变种是64位版的MT19937-64。 对于一个k位的长度,Mersenne Twister会在的区间之间生成离散型均匀分布的随机数。
应用
梅森旋转算法是R,Python,Ruby,IDL,Free Pascal,PHP,Maple,Matlab,GMP和GSL的默认伪随机数产生器。从C++11开始,C++也可以使用这种算法。在Boost C++,Glib和NAG数值库中,作为插件提供。 在SPSS中,梅森选旋转算法是两个PRNG中的一个:另一个是产生器仅仅为保证旧程序的兼容性,梅森旋转被描述为”更加可靠“。梅森旋转在SAS中同样是PRNG中的一个,另一个产生器是旧时的且已经被弃用。
优点
最为广泛使用Mersenne Twister的一种变体是MT19937,可以产生32位整数序列。具有以下的优点:
- 有219937 − 1的非常长的周期。在许多软件包中的短周期—232 随机数产生器在一个长周期中不能保证生成随机数的质量。[2]
- 在1 ≤ k ≤ 623的维度之间都可以均等分布(参见定义).
- 除了在统计学意义上的不正确的随机数生成器以外, 在所有伪随机数生成器法中是最快的(当时)[3]
int n = distribution(generator);
这句是怎么产生出随机数的呢?