cpp-随机数

随机数生成算法有很多,C++11之前的C/C++只用了一种。C++11则提供下面三种可供选择:

  • linear_congruential_engine线性同余法
  • mersenne_twister_engine梅森旋转法
  • substract_with_carry_engine滞后Fibonacci
分布 描述
uniform_int_distribution 该分布接受一组上下限值作为构造函数的参数。之后得到的随机值就都是在这个范围中。我们可能得到的每个值的可能性是相同的,直方图将会是一个平坦的图像。这个分布就像是掷骰子,因为掷到骰子的每一个面的概率都是相等的。
normal_distribution 正态分布或高斯分布,自然界中几乎无处不在。其STL版本能接受一个平均值和一个标准差作为构造函数的参数,其直方图的形状像是屋顶一样。其分布于人类个体高度或动物的IQ值,或学生的成绩,都符合这个分布。
bernoulli_distribution 当我们想要一个掷硬币的结果时,使用伯努利分布就非常完美。其只会产生0和1,并且其构造函数的参数是产生1的概率。
discrete_distribution 当我们有一些限制的时候,我们就可以使用离散分布,需要我们为每个间隔的概率进行定义,从而得到离散集合的值。其构造函数会接受一个权重值类别,并且通过权重值的可能性产生相应的随机数。当我们想要对血型进行随机建模时,每种血型的概率是不一样,这样这种引擎就能很完美地契合这种需求。
// 生成随机模拟数据
#include<random>

std::default_random_engine random;
for (int i = 0; i < 20; ++i)
int i = random();
// 生成模拟数据 发送
for (int i = 0; i < pwnd->m_sensorCount; ++i)
{
// obtain a seed from the system clock:
std::random_device rd;
std::mt19937 gen{ rd() };

std::uniform_real_distribution<double> dis(-100.0, 100.0);
vDataBuf.push_back(dis(gen));
}
// 生成 0- 100范围内的

#include<iostream>
#include<random>
#include<time.h>

using std::cout;
using std::endl;
using std::cin;


int main()
{
std::uniform_real_distribution<double> dis2(0.0, 1.0);

for(int i = 0; i < 10; ++i)
{
// obtain a seed from the system clock:
unsigned seed1 = std::chrono::system_clock::now().time_since_epoch().count();
std::default_random_engine random(seed1);
std::uniform_int_distribution<int> dis1(0, 100);
cout<<dis1(random)<<' ';
}

cout<<endl;

for(int i = 0; i < 10; ++i)
cout<<dis2(random)<<' ';
cout<<endl;

return 0;
}

在uniform_int_distribution的构造函数中,参数说明了随机数的范围。uniform_int_distribution的随机数的范围不是半开范围[  ),而是[  ],对于uniform_real_distribution却是半开范围[  )。也是就是说上面的例子中,能产生100,但不会产生1.0。不得不说,这颠覆了之前的认识。对于default_random_engine来说,其产生的随机数范围是在[min(), max()]之间,其中min()和max()为它的两个成员函数。同样,也是非半开范围。对于浮点数,如果真的是想产生[0.0, 1.0]范围的数,可以使用

#include<cmath>
#include<cfloat>
std::uniform_real_distribution<double> dis2(0, std::nextafter(1,DBL_MAX));

指定概率

discrete_distribution 参数是从 0-5 的数值出现的概率。
然后根据想要的数值范围 * 一个随机系数,得到范围值

std::random_device rd;
std::mt19937 gen(rd());
std::discrete_distribution<> d({ 1, 5, 14, 30,30,20 });
std::map<int, int> m;
int m1, m2;
for (int n = 0; n < 10000; ++n) {
m1 = d(gen);
++m[m1];
}
for (auto p : m) {
string str = to_string(p.first) + " generated " + to_string(p.second) + " times\r\n";
_cprintf(str.c_str());
}