- Published on
随机数
- Authors

- Name
- 东哥
前言
使用c++时经常要用到随机数, 本文对c++的随机数api做个简单的总结
传统方法
c++11之前一般会用srand()配合rand()来实现随机数的使用
比如
for (int i=0; i<10;i++)
{
cout << rand() % 10 << " ";//返回0-9的随机数
}

for (int i=0; i<10;i++)
{
srand(1);
cout << rand() % 10 << " ";
}

for (int i=0; i<10;i++)
{
srand(i%2);
cout << rand() % 10 << " ";
}

c++11随机数算法
c++11提供了3个新的随机算法
- linear_congruential_engine线性同余法
- mersenne_twister_engine梅森旋转法
- substract_with_carry_engine滞后Fibonacci
借用网络图用一下

如果我们要使用这三个模板类的话,就必须自己实例化之。但这些实例化参数都是这些算法里面使用到的参数,如果不懂算法的原理的话,真的不知道需要用什么参数才能得到比较好的随机序列。所以我们这些卑微的码农是用不了这些模板类的。C++11标准也想到了这点,所以就帮我们预定义了一些随机数类,这些随机数类都是用比较好的参数实例化上面那三个模板类。注意:在C++11里面,把这些随机数生成器叫做引擎(engines)。
直接开撸
std::default_random_engine random;
for (int i=0; i<10;i++)
{
cout << random() << endl;
}
结果就不显示了, 一堆随机数
同样的, 也可以设置随机种子(seed),方法是往构造函数传入参数或者使用 random.seed()来设置
std::default_random_engine random(1);
//等价于 random.seed(1);
std::default_random_engine random;
std::uniform_int_distribution<int> dis1(0, 100);
std::uniform_real_distribution<double> dis2(0.0, 1.0);
for (int i=0; i<10;i++)
{
cout << dis1(random) <<endl;
cout << dis2(random) << endl;
}

用上述两个模板类来生成的均是均匀分布的随机数, 基本已经能满足一般的项目需求了
需要注意的是
uniform_int_distribution的随机数的范围是
[ ]uniform_real_distribution却是半开范围
[ )如果需要浮点数随机范围是
[],那么按照如下使用std::uniform_real_distribution<double> dis2(0, std::nextafter(1,DBL_MAX));
其他算法
C++11提供的概率分布类型有下面这些:
均匀分布:
uniform_int_distribution 整数均匀分布
uniform_real_distribution 浮点数均匀分布
伯努利类型分布:(仅有yes/no两种结果,概率一个p,一个1-p)
bernoulli_distribution 伯努利分布
binomial_distribution 二项分布
geometry_distribution 几何分布
negative_biomial_distribution 负二项分布
Rate-based distributions:
poisson_distribution 泊松分布
exponential_distribution指数分布
gamma_distribution 伽马分布
weibull_distribution 威布尔分布
extreme_value_distribution 极值分布
正态分布相关:
normal_distribution 正态分布
chi_squared_distribution卡方分布
cauchy_distribution 柯西分布
fisher_f_distribution 费歇尔F分布
student_t_distribution t分布
分段分布相关:
discrete_distribution离散分布
piecewise_constant_distribution分段常数分布
piecewise_linear_distribution分段线性分布
泊松分布
std::default_random_engine random;
std::uniform_int_distribution<int> dis1(0, 100);
std::uniform_real_distribution<double> dis2(0.0, 1.0);
std::poisson_distribution<int> dis3(2.5);
int p[10] = {};
for (int i=0; i<10000;i++)
{
int n = dis3(random);
if (n < 10)
{
p[n]++;
}
}
for (int i =0; i< 10; i++)
{
cout<< i << " : "<< string(p[i]*0.01, '*') << endl;
}

上图显示的就是如下图的情况
