记录一下 C++ 里的随机数。
C风格随机数生成器
import std;
using namespace std;
int main()
{
srand(static_cast<unsigned int>(time(nullptr)));
cout << rand() << endl;
}
生成范围在0
到RAND_MAX
之间,生成的随机数低位不是非常随机。
C++随机数引擎
有以下随机数引擎可以使用:
random_device
linear_congruential_engine
mersenne_twister_engine
substract_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);