导入
随机数
有一个完整的库专门用于随机数的生成和使用。
C++ 继承了 C 语言的数值函数,并提供了专门的随机数库。
随机数在许多领域中都至关重要,例如软件测试、生成加密密钥或开发计算机游戏。C++ 的随机数功能由两个组件构成:随机数的生成和随机数的分布。这两个组件都需要包含头文件 <random>。
随机数生成器
随机数生成器用于生成介于最小值和最大值之间的一系列随机数值。该序列通过一个所谓的“种子”(seed)进行初始化,以确保每次运行时产生不同的随机数序列。
1#include <random> 2... 3std::random_device seed; 4std::mt19937 generator(seed());
一个类型为 Generator 的随机数生成器 gen 支持四种操作:
Generator::result_type:生成的随机数的数据类型。gen():返回一个随机数。gen.min():返回gen()可生成的最小随机数值。gen.max():返回gen()可生成的最大随机数值。
C++ 随机数库支持多种随机数生成器。最著名的包括梅森旋转算法(Mersenne Twister)、由实现自行选择的默认引擎 std::default_random_engine,以及 std::random_device。其中,std::random_device 是唯一的真随机数生成器,但并非所有平台都提供支持。
随机数分布
随机数分布利用随机数生成器 gen 将生成的原始随机数映射到指定的概率分布上。
1#include <random> 2... 3std::random_device seed; 4std::mt19937 gen(seed()); 5std::uniform_int_distribution<> unDis(0, 20); // 分布范围为 0 到 20 6unDis(gen); // 生成一个随机数
C++ 提供了多种离散型和连续型的随机数分布。离散分布生成整数,而连续分布生成浮点数。
1class bernoulli_distribution; 2template<class T = int> class uniform_int_distribution; 3template<class T = int> class binomial_distribution; 4template<class T = int> class geometric_distribution; 5template<class T = int> class negative_binomial_distribution; 6template<class T = int> class poisson_distribution; 7template<class T = int> class discrete_distribution; 8template<class T = double> class exponential_distribution; 9template<class T = double> class gamma_distribution; 10template<class T = double> class weibull_distribution; 11template<class T = double> class extreme_value_distribution; 12template<class T = double> class normal_distribution; 13template<class T = double> class lognormal_distribution; 14template<class T = double> class chi_squared_distribution; 15template<class T = double> class cauchy_distribution; 16template<class T = double> class fisher_f_distribution; 17template<class T = double> class student_t_distribution; 18template<class T = double> class piecewise_constant_distribution; 19template<class T = double> class piecewise_linear_distribution; 20template<class T = double> class uniform_real_distribution;
带有默认模板参数 int 的类模板属于离散分布。伯努利分布(bernoulli_distribution)生成布尔值。
以下示例使用梅森旋转算法 std::mt19937 作为伪随机数生成器,生成 100 万个随机数,并将这些随机数分别映射到均匀分布和正态分布(高斯分布)上。
1#include <cstdlib> 2#include <fstream> 3#include <iostream> 4#include <map> 5#include <random> 6 7static const int NUM = 1000000; 8 9void writeToFile(const char* fileName, const std::map<int, int>& data) { 10 std::ofstream file(fileName); 11 12 if (!file) { 13 std::cerr << "无法打开文件 " << fileName << "。"; 14 exit(EXIT_FAILURE); 15 } 16 17 // 将数据点写入文件 18 for (const auto& mapIt : data) 19 file << mapIt.first << " " << mapIt.second << std::endl; 20} 21 22int main() { 23 std::random_device seed; 24 25 // 默认生成器 26 std::mt19937 engine(seed()); 27 28 // 定义各种分布 29 std::uniform_int_distribution<> uniformDist(0, 20); // 范围:0 到 20 30 std::normal_distribution<> normDist(50, 8); // 均值=50,标准差=8 31 std::poisson_distribution<> poiDist(6); // 均值=6 32 std::gamma_distribution<> gammaDist; // 形状参数 alpha=1 33 34 std::map<int, int> uniformFrequency; 35 std::map<int, int> normFrequency; 36 std::map<int, int> poiFrequency; 37 std::map<int, int> gammaFrequency; 38 39 for (int i = 1; i <= NUM; ++i) { 40 ++uniformFrequency[uniformDist(engine)]; 41 ++normFrequency[round(normDist(engine))]; 42 ++poiFrequency[poiDist(engine)]; 43 ++gammaFrequency[round(gammaDist(engine))]; 44 } 45 46 writeToFile("uniform_int_distribution.txt", uniformFrequency); 47 writeToFile("normal_distribution.txt", normFrequency); 48 writeToFile("poisson_distribution.txt", poiFrequency); 49 writeToFile("gamma_distribution.txt", gammaFrequency); 50}
下图展示了 100 万个随机数在均匀分布和正态分布下的统计结果:

