17.4 Random Numbers(随机数)
程序使用rand()来生成谁技术,此函数生成的是伪随机数,每个随机数的范围在0到一个系统相关的最大数(至少为32767)之间。
C++通过定义在random中的随机数引擎类和随机数分布类来生成unsigned随机数。
引擎:生成随机unsigned整数序列
分布:使用引擎返回特定概率分布的随机数
C++程序不应该使用库函数rand,而应使用default_random_engine类和恰当的分布类对象。
#include <iostream> #include <random> using namespace std; int main() { default_random_engine e; for (int i = 0; i < 10; i++) cout << e() << ends; return 0; }
上面是随机数引擎的输出,一般不能直接使用。
| 式子 | 说明 |
| 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 |
通过分布类型对象,获得指定范围的数。
#include <iostream> #include <random> using namespace std; int main() { uniform_int_distribution<unsigned> u(0, 9); default_random_engine e; for (int i = 0; i < 10; i++) cout << u(e) << ends; system("PAUSE"); return 0; }
类似引擎类型,分布类型也是函数对象类。
注意:我们传递给分布对象的是引擎对象本身,即u(e)
随机数发生器:分布对象和引擎对象的组合。
#include <iostream> #include <string> #include <random> #include <vector> #include <ctime> using namespace std; vector<unsigned> func() { uniform_int_distribution<unsigned> u(0, 9); default_random_engine e(time(0)); vector<unsigned> vec; for (int i = 0; i < 10; ++i) { vec.push_back(u(e)); } return vec; } vector<unsigned> func1() { static uniform_int_distribution<unsigned> u(0, 9); static default_random_engine e; vector<unsigned> vec; for (int i = 0; i < 10; ++i) { vec.push_back(u(e)); } return vec; } int main() { vector<unsigned> vec1(func()), vec2(func()); cout << ((vec1 == vec2) ? "相同" : "不同") << endl; for (auto& i : vec1) { cout << i << " "; } cout << endl; for (auto& i : vec2) { cout << i << " "; } //func(); vector<unsigned> vec3(func1()), vec4(func1()); cout << ((vec3 == vec4) ? "相同" : "不同") << endl; for (auto& i : vec3) { cout << i << " "; } cout << endl; for (auto& i : vec4) { cout << i << " "; } cout << endl; uniform_real_distribution<double> f(0,1); default_random_engine r(time(NULL)); vector<double> vec5, vec6; for (int i = 0; i < 10; ++i) { vec5.push_back(f(r)); } for (auto& i : vec5) { cout << i << " "; } cout << endl; for (int i = 0; i < 10; ++i) { vec6.push_back(f(r)); } for (auto& i : vec6) { cout << i << " "; } system("PAUSE"); return 0; }
一个给定的随机数发生器一直会生成相同的随机数序列。一个函数如果定义了局部的随机数发生器,应该将其(包括引擎和分布对象)定义为static的。否则,每次调用函数都会生成相同的序列。
选择一个好的种子,与生成好的随机数所涉及的其他大多数事情相同,是极其困难的。可能最常用的方法是调用系统函数time。这个函数定义在头文件ctime中,它返回从一个特定时刻到当前经过了多少秒。函数time接受单个指针参数,它指向用于写入时间的数据结构。如果此指针为空,则函数简单地返回时间。
default_random_engine e(time(NULL));
由于time返回以秒计的时间,因此这种方式只适用于生成种子的间隔为秒级或更长的应用。
如果程序作为一个自动过程的一部分反复运行,将time的返回值作为种子的方式就无效了;它可能多次使用的都是相同的种子。
使用normal_distribution生成浮点值。
#include <string> #include <iostream> #include <vector> #include <cmath> #include <ctime> #include <random> #define N 200 using namespace std; int main() { default_random_engine e(time(NULL)); normal_distribution<> n(4, 1.5);//正态分布,均值为4,标准差为1.5 vector<unsigned> vec(9); for (size_t i = 0; i < N; ++i) { unsigned num = lround(n(e));//取离浮点数最近的整数 if (num < vec.size()) ++vec[num]; } for (size_t i = 0; i < vec.size(); ++i) cout << vec[i] << ":" << string(vec[i], '*') << endl; system("PAUSE"); return 0; }
bernoulli_distribution类总是返回一个bool值

浙公网安备 33010602011771号