C++ 里的随机数

记录一下 C++ 里的随机数。

C风格随机数生成器

import std;
using namespace std;

int main()
{
	srand(static_cast<unsigned int>(time(nullptr)));
	cout << rand() << endl;
}

生成范围在0RAND_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 的周期为,状态包含 625 个整数,约为 2.5 KB。

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_rand0linear_congruential_engine
minstd_randlinear_congruential_engine
mt19937mersenne_twister_engine
mt19937_64mersenne_twister_engine
ranlux24_basesubtract_with_carry_engine
ranlux48_basesubtract_with_carry_engine
ranlux24discard_block_engine
ranlux48discard_block_engine
knuth_bshuffle_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);