C11 随机数

看到了 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年开发,基于有限二进制字段上的矩阵线性递归F_{2}。可以快速产生高质量的伪随机数, 修正了古典随机数发生算法的很多缺陷。

Mersenne Twister这个名字来自周期长度取自梅森素数的这样一个事实。这个算法通常使用两个相近的变体,不同之处在于使用了不同的梅森素数。一个更新的和更常用的是MT19937, 32位字长。 还有一个变种是64位版的MT19937-64。 对于一个k位的长度,Mersenne Twister会在[0,2^k-1]的区间之间生成离散型均匀分布的随机数。

应用

梅森旋转算法是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位整数序列。具有以下的优点:

  1. 有219937 − 1的非常长的周期。在许多软件包中的短周期—232 随机数产生器在一个长周期中不能保证生成随机数的质量。[2]
  2. 在1 ≤ k ≤ 623的维度之间都可以均等分布(参见定义).
  3. 除了在统计学意义上的不正确的随机数生成器以外, 在所有伪随机数生成器法中是最快的(当时)[3]

由此可以看出,VS2010上正是用了MT19937这种算法。
在使用的时候,构造函数可以传参,我们传了个time(0),其实就是个long整数。就根据这个参数产生种子。具体的随机算法暂时不研究了。
然后我们用了uniform_int_distribution这个均匀分布的东东,可以在构造时指定min,max;
关键是:
int n = distribution(generator);

这句是怎么产生出随机数的呢?
生成器generator:能够产生离散的等可能分布数值
分布器distributions: 能够把generator产生的均匀分布值映射到其他常见分布,如均匀分布uniform,正态分布normal,二项分布binomial,泊松分布poisson;
所以就明白了就是把generator产生的随机数,再次投影到均匀分布上。
嗯,好吧,准备下班回家。 微笑




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值