C++11随机数

c++11 伪随机数生成

c++11 随机数库<random>提供生成随机数和伪随机数的类,
为生成伪随机数,主要包括两类

  1. 均匀随机位生成器(URBG),包含随机数引擎,它们是伪随机数生成器,是能够生成均匀分布整数序列的伪随机数
  2. 随机数分布(例如均匀分布,正态分布和泊松分布等),它们将 URBG 的输出转换为各种统计分布
    均匀随机位生成器和随机数分布相互使用。所有随机数引擎都可以指定地播种、序列化和反序列化,以用于可重复的模拟器

均匀随机位生成器

均匀随机位生成器是函数对象(仿函数类),它返回无符号整数值,并使得每个值在可能结果的范围中拥有(理想上)相等的被返回概率
主要有以下4种,

  1. 随机数引擎
    随机数引擎本质是一种算数算法,因此相同的种子多次调用产生的随机数是完全相同的
    标准提供三种常用的引擎:linear_congruential_engine,mersenne_twister_engine 和 subtract_with_carry_engine。第一种是线性同余算法,第二种是梅森旋转算法,第三种带进位的线性同余算法。
  2. 随机数引擎适配器
    随机数引擎适配器生成以另一随机数引擎为熵源的伪随机数
  3. 预定义随机数生成器
    具体见伪随机数生成
    常用的有default_random_engine,mt19937,minstd_rand0等
  4. 非确定随机数生成器
    使用硬件熵源的非确定随机数生成器
    std::random_device

使用方法
正常使用我们只需要使用预定义随机数生成器或者非确定随机数即可
随机数引擎接受一个整形参数当作种子,不提供的话,会使用默认值。如果想多次运行产生相同的随机数,可以使用一个确定的数作为种子。如果是想每次运行生成不一样的随机数,Linux 推荐使用 random_device 来产生一个随机数当作种子,windows 产生一个伪随机数作为种子。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
#include <random>
int main(){
//选择某一种随机数生成器或者
std::random_device rd; //使用硬件熵源
//将rd生成的非确定随机数作为随机数引擎的种子,当然自定义也行,相同的种子多次调用产生的随机数是完全相同
std::default_random_engine e(rd());
//生成10个随机数
for(int i = 0; i < 10; i++){
std::cout<<e()<<std::endl;
}
return 0;

}

随机数分布

随机数分布后处理 URBG 的输出,以使得输出结果按照定义的统计概率密度函数分布
具体间随机数分布中提供的类,常见的有均匀,正态等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main()
{
// 以随机值播种,若可能
std::random_device r;

// 选择 1 与 6 间的随机数
std::default_random_engine e1(r());
std::uniform_int_distribution<int> uniform_dist(1, 6);
int mean = uniform_dist(e1);
std::cout << "Randomly-chosen mean: " << mean << '\n';


// 值最可能接近平均
// 标准差影响生成的值距离平均数的分散
std::random_device rd;
std::mt19937 gen(rd());
std::normal_distribution<> d{5,2};
std::map<int, int> hist{};
for(int n=0; n<10000; ++n) {
++hist[std::round(d(gen))];
}
for(auto p : hist) {
std::cout << std::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*') << '\n';
}
}