linear_congruential_engine 实现线性同余算法 mersenne_twister_engine 实现梅森缠绕器算法 subtract_with_carry_engine 实现带进位减(一种延迟斐波那契)算法 以上三个引擎都是类模板,它们第一个模板参数都是UIntType,表示生成数字的类型,且在内部被定义为result_type成员类型,其他模板参数是特定算法需要的参数。 它们的构造函数类似,以linear_congruential_engine为例说明:
linear_congruential_engine() : linear_congruential_engine(default_seed) {} (1) explicit linear_congruential_engine(result_type value); (2) template <class Sseq> explicit linear_congruential_engine(Sseq& s); (3) linear_congruential_engine(const linear_congruential_engine&); (4)(隐式声明) 构造引擎并初始化状态。 (1)默认构造函数。以 default_seed 播种引擎。 仅若 Sseq 符合种子序列要求,(3)才参与重载决议。尤其是若 Sseq 可转换为 result_type,则从候选函数集中排除该重载。类 std::seed_seq 满足种子序列的要求。一个 seed_seq 对象消耗整数值数列,并基于消耗的数据生成请求数量的无符号整数值 i,0<=i < 2^32。产生的值分布在整个 32 位范围上,即使消耗的值接近。seed_seq 的构造函数和 generate 函数声明如下:
seed_seq(); seed_seq(const seed_seq&) = delete; template <class InputIt> seed_seq(InputIt begin, InputIt end); template <class T> seed_seq(std::initializer_list<T> il); template <class RandomIt> void generate(RandomIt begin, RandomIt end);一个简单的例子:
#include <random> #include <cstdint> #include <iostream> int main() { std::seed_seq seq{1,2,3,4,5}; std::vector<std::uint32_t> seeds(10); seq.generate(seeds.begin(), seeds.end()); for (std::uint32_t n : seeds) { std::cout << n << '\n'; } return 0; }回到三个随机数引擎上,它们还有一些公共的成员函数:
void seed(result_type value = default_seed); template <class Sseq> void seed(Sseq& seq); 用新种子值重新初始化随机数引擎的内部状态。 result_type operator()(); 生成伪随机数。令引擎状态前进一个位置。 void discard(unsigned long long z); 令内部状态前进 z 次。等价于调用 operator() z 次并舍弃结果。 static constexpr result_type min(); 返回随机数引擎潜在生成的最小值。此值等于 0u 。 static constexpr result_type max(); 返回随机数引擎潜在生成的最大值。此外还有以下非成员函数:
operator== operator!= 比较两个伪随机数引擎的内部状态 operator<< operator>> 执行伪随机数引擎的流输入和输出 前者序列化引擎的内部状态为一或多个空格分隔的十进制数序列,并插入到流。后者能将十进制数序列还原为原引擎。std::random_device 是生成非确定随机数的均匀分布整数随机数生成器。 std::random_device 可以以实现定义的伪随机数引擎实现,在某些实现中可能每个 std::random_device 对象生成同一数值序列。 std::random_device 一般作为其他随机数引擎的种子使用。
random_device() : random_device(/*implementation-defined*/) {} explicit random_device(const std::string& token); 标准期待 token 指定产生随机数字的字节设备,比如 linux 下的 /dev/random 。 random_device(const random_device& ) = delete; random_device& operator=(const random_device&) = delete; result_type operator()(); 生成均匀分布的非确定随机值。 static constexpr result_type min(); 返回随机数引擎潜在生成的最小值。此值等于 0u 。 static constexpr result_type max(); 返回随机数引擎潜在生成的最大值。此值等于 std::numeric_limits<unsigned int>::max() 。简单例子:
#include <iostream> #include <random> int main() { std::uniform_int_distribution<int> d(0, 10); std::random_device rd1; // 使用 RDRND 或 /dev/urandom for(int n = 0; n < 10; ++n) std::cout << d(rd1) << ' '; std::cout << '\n'; std::random_device rd2("/dev/random"); // Linux 上更慢 for(int n = 0; n < 10; ++n) std::cout << d(rd2) << ' '; std::cout << '\n'; }一般来说像下面这样用:
#include <random> #include <iostream> int main() { std::random_device rd; std::default_random_engine gen(rd()); for(int i=0; i<10; ++i) std::cout << gen() << ' '; return 0; }简单例子:
#include <random> #include <iostream> int main() { std::random_device rd; std::mt19937 gen(rd()); for(int n = 0; n < 10; ++n) { std::cout << std::generate_canonical<double, 10>(gen) << ' '; } }uniform_int_distribution 产生在一个范围上均匀分布的整数值。(类模板) uniform_real_distribution 产生在一个范围上均匀分布的实数值。(类模板)
bernoulli_distribution 产生伯努利分布上的 bool 值。(类) binomial_distribution 产生二项分布上的整数值。(类模板) negative_binomial_distribution 产生负二项分布上的整数值。(类模板) geometric_distribution 产生几何分布上的整数值。(类模板)
poisson_distribution 产生泊松分布上的整数值。(类模板) exponential_distribution 产生指数分布上的实数值。(类模板) gamma_distribution 产生 Γ 分布上的实数值(类模板) weibull_distribution 产生威布尔分布上的实数值。(类模板) extreme_value_distribution 产生极值分布上的实数值。(类模板)
normal_distribution 产生标准正态(高斯)分布上的实数值。(类模板) lognormal_distribution 产生对数正态分布上的实数值。(类模板) chi_squared_distribution 产生 χ2 分布上上的实数值。(类模板) cauchy_distribution 产生柯西分布上的实数值。(类模板) fisher_f_distribution 产生费舍尔 F 分布上的实数值。(类模板) student_t_distribution 产生学生 t 分布上的实数值。(类模板)
discrete_distribution 产生离散分布上的随机整数。(类模板) piecewise_constant_distribution 产生分布在常子区间上的实数值。(类模板) piecewise_linear_distribution 产生分布在定义的子区间上的实数值。(类模板)
以上的类或类模板使用方式都是类似的,构造函数根据参数生成概率分布函数,使用operator()()根据关联的概率分布函数生成随机数。 他们主要有以下常用成员:
成员类型result_type,operator()()的返回值。 void reset(); 重置分布对象的内部状态 template <class Generator> result_type operator()(Generator& g); 根据关联的概率分布函数生成随机数。由调用 g.operator() 获得熵。 result_type min() const; 返回分布潜在生成的最小值。 result_type max() const; 返回分布潜在生成的最大值。看一个正态分布的例子:
#include <iostream> #include <iomanip> #include <string> #include <map> #include <random> #include <cmath> int main() { std::random_device rd{}; std::mt19937 gen{rd()}; // 值最可能接近平均 // 标准差影响生成的值距离平均数的分散 std::normal_distribution<> d{5,2}; std::map<int, int> hist; for(int n=0; n<50000; ++n) { ++hist[std::round(d(gen))]; } for(auto &p : hist) { std::cout << std::setw(2) << p.first << ' ' << std::string(p.second/200, '*') << '\n'; } return 0; }输出是:
-4 -3 -2 -1 0 ** 1 ******* 2 *************** 3 ****************************** 4 ******************************************* 5 ************************************************* 6 ******************************************* 7 ****************************** 8 **************** 9 ****** 10 ** 11 12 13 14参考 cppreference.com cplusplus.com
