- C++ 随机数库定义在 random 头文件中。
- C++ 随机数库由一组协作类构成:随机数引擎类、随机数分布类
- 引擎:类型,生成随机 unsigned 整数序列
- 分布:类型,使用引擎返回特定概率分布的随机数
随机数引擎和分布
随机数引擎
操作 | 说明 |
Engine e; | 默认构造函数;使用该引擎类型默认的种子 |
Engine e(s); | 使用整型值 s 作为种子 |
e.seed(s); | 使用种子 s 重置引擎的状态 |
e.min(); | 此引擎生成的最小值 |
e.max(); | 此引擎生成的最大值 |
Engine::result_type | 此引擎生成的 unsigned 整型类型 |
e.discard(u) | 将引擎推进 u 步;u的类型为unsigned long long |
分布类型和引擎
为了得到在一个指定范围内的数,需要使用一个分布类型的对象:
default_random_engine e;
uniform_int_distribution<unsigned> dis(0, 9);
for (int i = 0; i < 10;i++)
cout << dis(e) << endl;
注意,传递给分布对象的是引擎对象本身,如果传递的是 u(e())
,含义就变成将 e 生成的下一个值传递给 u,会导致编译错误。
一个给定的随机数发生器一直会生成相同的随机数序列,一个函数如果定义了局部的随机数发生器,应将引擎和分布对象定义成 static 类型,否则每次调用函数都会生成相同的序列。
vector<unsigned> bad_randVec()
{
default_random_engine e;
uniform_int_distribution<unsigned> dis(0,9);
vector<unsigned> res;
for (size_t i = 0; i < 100; i++)
res.push_back(dis(e));
return res;
}
vector<unsigned> good_randVec()
{
static default_random_engine e;
static uniform_int_distribution<unsigned> dis(0, 9);
vector<unsigned> res;
for (size_t i = 0; i < 100; i++)
res.push_back(dis(e));
return res;
}
int main()
{
vector<unsigned> vec1 = bad_randVec();
vector<unsigned> vec2 = bad_randVec();
cout << (vec1 == vec2) << endl; //@ true
vector<unsigned> vec3 = good_randVec();
vector<unsigned> vec4 = good_randVec();
cout << (vec3 == vec4) << endl; //@ false
return 0;
}
设置随机数发生器种子
随机数发生器会生成相同的随机数序列这一特性在调试中很有用。
如果我们希望每次程序运行都会产生不同的随机结果,可以提供种子来达到这一目的,种子就是一个数值,引擎可以利用它从序列中一个新位置重新开始生成随机数。
设置种子有两种方式:
- 在创建引擎对象时提供种子。
- 调用 seed 设置种子。
default_random_engine e1; //@ 使用默认的种子
default_random_engine e2(32767); //@ 使用给定的种子
default_random_engine e3;
e3.seed(100); //@ 使用 seed 设置种子
default_random_engine e4(time(0)); //@ 使用 time() 产生随机种子
生成随机实数
default_random_engine e;
uniform_real_distribution<double> u(0,1); //@ 指明数据的范围
for (size_t i = 0; i < 10; i++)
cout << u(e) << endl;
生成非均匀分布的随机数
新标准库定义了20种分布类型:
正太分布
default_random_engine e;
normal_distribution<> n(4, 1.5); //@ 均值4,标准差1.5
vector<unsigned> vals(9);
for (size_t i = 0; i != 200; i++)
{
unsigned v = lround(n(e));
if (v < vals.size())
++vals[v];
}
for (size_t j = 0; j != vals.size(); ++j)
{
cout << j << ": " << string(vals[j], '*') << endl;
}
伯努利分布
default_random_engine e;
bernoulli_distribution b;
for (size_t i = 0; i < 5; i++)
cout << b(e) << endl;