记录一下 C++ 里的随机数。
C风格随机数生成器
import std;using namespace std;
int main(){ srand(static_cast<unsigned int>(time(nullptr))); cout << rand() << endl;}
生成范围在0
到RAND_MAX
之间,生成的随机数低位不是非常随机。
C++随机数引擎
有以下随机数引擎可以使用:
random_devicelinear_congruential_enginemersenne_twister_enginesubstract_with_carry_engine
random_device
当计算机具有或者连接能生成真随机数的硬件时使用这个硬件,没有时则根据标准库实现使用内部的一个软件替代算法
random_device rnd;cout << "Entropy:" << rnd.entropy() << endl;cout << "Min value:" << rnd.min << ",Max value:" << rnd.max() << endl;cout << "Random number:" << rnd() << endl;
生成速度较慢,一般可以用它生成随机数种子。
linear_congruential_engine(线性同余引擎)
保存状态所需的内存量最少。保存的状态是一个包含上一次生成的随机数的整数。周期取决于算法参数,最高有
mersenne_twister_engine (梅森旋转引擎)
周期为梅森素数。最常用的也是预定义的梅森旋转算法 mt19937 的周期为
substract_with_carry_engine (带进位减法引擎)
要求保存约 100 字节的状态。但生成的随机数质量不如梅森旋转算法。
实际使用这些引擎需要一些(实际上相当多)的数学参数,一般使用预定义的随机数引擎参数。
随机数引擎适配器
template<class Engine, size_t p, size_t r> class discard_block_engine {...}template<class Engine, size_t w, class UIntT> class independent_bits_engine {...}template<class Engine, size_t k> class shuffle_order_engine {...}
discard_block_engine
适配器通过丢弃基引擎生成的一些值来生成随机数。它需要三个参数:要适配的引擎、块大小p
和使用的块大小r
。基引擎用于生成p
个随机数。适配器丢弃其中的p-r
个,并返回剩下的r
个数。
independent_bits_engine
适配器通过组合基引擎生成的几个随机数来生成具有给定位数w
的随机数。
shuffle_order_engine
适配器生成的随机数与基引擎生成的一致,但顺序不同。模板参数k
是适配器使用的内部表的大小。该适配器根据请求从该表中随机选择一个随机数,然后用基引擎生成的新随机数替换。
预定义的随机数引擎和引擎适配器
预定义生成器 | 类模板 |
---|---|
minstd_rand0 | linear_congruential_engine |
minstd_rand | linear_congruential_engine |
mt19937 | mersenne_twister_engine |
mt19937_64 | mersenne_twister_engine |
ranlux24_base | subtract_with_carry_engine |
ranlux48_base | subtract_with_carry_engine |
ranlux24 | discard_block_engine |
ranlux48 | discard_block_engine |
knuth_b | shuffle_order_engine |
default_random_engine | 由实现定义 |
使用
random_device seeder;const auto seed{seeder.entropy() ? seeder() : time(nullptr)};
mt19937 engine{static_cast<mt19937::result_type>(seed)};uniform_int_distribution<int> distribution{1, 99};cout << distribution(engine) << endl;
auto generator{bind(distribution, engine)};vector<int> values(10);generate(begin(values), end(values), generator);for (auto i : values){ cout << i << " ";}
随机数分布
以下为可用的随机数分布:
均匀分布:
template<class IntType = int> class uniform_int_distribution uniform_int_distribution(IntType a = 0, IntType b = numeric_limits<IntType>::max());template<class RealType = double> class uniform_real_distribution uniform_real_distribution(RealType a = 0.0, RealType b = 1.0);
伯努利分布:
class bernoulli_distribution bernoulli_distribution(double p = 0.5);template<class IntType = int> class binomial_distribution binomial_distribution(IntType t = 1, double p = 0.5);template<class IntType = int> class geometric_distribution geometric_distribution(double p = 0.5);template<class IntType = int> class negative_binomial_distribution negative_binomial_distribution(IntType k = 1, double p = 0.5);
泊松分布:
template<class IntType = int> class poisson_distribution poisson_distribution(double mean = 1.0);template<class RealType = double> class exponential_distribution exponential_distribution(RealType lambda = 1.0);template<class RealType = double> class gamma_distribution gamma_distribution(RealType alpha = 1.0, RealType beta = 1.0);template<class RealType = double> class weibull_distribution weibull_distribution(RealType a = 1.0, RealType b = 1.0);template<class RealType = double> class extreme_value_distribution extreme_value_distribution(RealType a = 0.0, RealType b = 1.0);
正态分布:
template<class RealType = double> class normal_distribution normal_distribution(RealType mean = 0.0, RealType stddev = 1.0);template<class RealType = double> class lognormal_distribution lognormal_distribution(RealType m = 0.0, RealType s = 1.0);template<class RealType = double> class chi_squared_distribution chi_squared_distribution(RealType n = 1);template<class RealType = double> class cauchy_distribution cauchy_distribution(RealType a = 0.0, RealType b = 1.0);template<class RealType = double> class fisher_f_distribution fisher_f_distribution(RealType m = 1, RealType n = 1);template<class RealType = double> class student_t_distribution student_t_distribution(RealType n = 1);
采样分布:
template<class IntType = int> class discrete_distribution discrete_distribution(initializer_list<double> wl);template<class RealType = double> class piecewise_constant_distribution template<class UnaryOperation> piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw);template<class RealType = double> class piecewise_linear_distribution template<class UnaryOperation> piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw);