我最近遇到了在C++ 11中生成随机数的新方法,但无法消化我读到的关于它的论文(什么是引擎,数学术语如分布,"所有生成的整数同样可能 ").
所以任何人都可以解释
您可以在一个有关随机数生成的常见问题解答中调用它.
Ker*_* SB 131
这个问题对于一个完整的答案来说过于宽泛,但让我选择几个有趣的观点:
假设你有一个简单的随机数生成器,它们生成数字0,1,...,10,每个都具有相同的概率(将其视为经典rand()).现在你想要一个0,1,2范围内的随机数,每个都有相同的概率.你的下意识反应就是采取行动rand() % 3.但是等一下,剩下的0和1比剩下的2更多,所以这不正确!
这就是为什么我们需要适当的分布,它采用统一随机整数的来源并将它们转换成我们想要的分布,就像Uniform[0,2]在例子中一样.最好把它留给一个好的图书馆!
因此,所有随机性的核心是一个好的伪随机数发生器,它产生一定数量的序列,这些数字在一定的时间间隔内均匀分布,并且理想情况下具有很长的周期.标准实施rand()通常不是最好的,因此有一个选择是好的.线性同余和梅森捻线机是两个不错的选择(LG实际上经常使用它rand()); 再次,让图书馆处理它是件好事.
简单:首先,设置一个引擎并播种它.种子完全确定"随机"数字的整个序列,因此a)/dev/urandom每次使用不同的数字(例如取自),和b)如果您希望重新创建一系列随机选择,则存储种子.
#include <random>
typedef std::mt19937 MyRNG; // the Mersenne Twister with a popular choice of parameters
uint32_t seed_val; // populate somehow
MyRNG rng; // e.g. keep one global instance (per thread)
void initialize()
{
rng.seed(seed_val);
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以创建发行版:
std::uniform_int_distribution<uint32_t> uint_dist; // by default range [0, MAX]
std::uniform_int_distribution<uint32_t> uint_dist10(0,10); // range [0,10]
std::normal_distribution<double> normal_dist(mean, stddeviation); // N(mean, stddeviation)
Run Code Online (Sandbox Code Playgroud)
...并使用引擎创建随机数!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
偏好<random>传统的一个更重要的原因rand()是现在非常清楚和明显如何使随机数生成线程安全:为每个线程提供自己的线程本地引擎,在线程本地种子上播种,或者同步访问到引擎对象.
result_type键入def ,这是用于种子的正确整数类型.我想我有一个错误的实现一次迫使我强制种子std::mt19937到uint32_tx64,最终这应该是固定的,你可以说MyRNG::result_type seed_val,从而使引擎很容易更换.随机数生成器是一个方程,给定一个数字,它会给出一个新数字。通常,您可以提供第一个数字,也可以从系统时间等中提取。
每次您请求一个新数字时,它都会使用以前的数字来执行方程式。
如果随机数生成器倾向于比其他数字更频繁地生成相同的数字,则该随机数生成器不会被视为非常好。即,如果您想要 1 到 5 之间的随机数,并且您的数字分布如下:
2 的生成频率远高于任何其他数字,因此它比其他数字更有可能生成。如果所有数字都一样,那么您每次都有 20% 的机会获得每个数字。换句话说,上面的分布很不均匀,因为 2 更受青睐。全部 20% 的分配是均匀的。
通常,如果您想要一个真正的随机数,您可以从天气或其他自然来源中提取数据,而不是从随机数生成器中提取数据。