C++ 11中的随机数生成:如何生成,它是如何工作的?

91 c++ random c++11

我最近遇到了在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()是现在非常清楚和明显如何使随机数生成线程安全:为每个线程提供自己的线程本地引擎,在线程本地种子上播种,或者同步访问到引擎对象.

杂项

  • 一个有趣的文章对TR1上codeguru随机的.
  • 维基百科有一个很好的总结(谢谢,@ Justin).
  • 原则上,每个引擎应该result_type键入def ,这是用于种子的正确整数类型.我想我有一个错误的实现一次迫使我强制种子std::mt19937uint32_tx64,最终这应该是固定的,你可以说MyRNG::result_type seed_val,从而使引擎很容易更换.

  • 对于"以某种方式填充"部分,我认为`std :: random_device`值得一提,而不是`/ dev/urandom` (13认同)
  • Kerrek 再次先发制人,给出了比我正在研究的答案更好的答案。+1 (2认同)
  • 可以在[这里]找到`std :: random_device`的示例(http://en.cppreference.com/w/cpp/numeric/random/random_device). (2认同)

N_A*_*N_A 5

随机数生成器是一个方程,给定一个数字,它会给出一个新数字。通常,您可以提供第一个数字,也可以从系统时间等中提取。

每次您请求一个新数字时,它都会使用以前的数字来执行方程式。

如果随机数生成器倾向于比其他数字更频繁地生成相同的数字,则该随机数生成器不会被视为非常好。即,如果您想要 1 到 5 之间的随机数,并且您的数字分布如下:

  • 1:1%
  • 2:80%
  • 3:5%
  • 4:5%
  • 5:9%

2 的生成频率远高于任何其他数字,因此它比其他数字更有可能生成。如果所有数字都一样,那么您每次都有 20% 的机会获得每个数字。换句话说,上面的分布很不均匀,因为 2 更受青睐。全部 20% 的分配是均匀的。

通常,如果您想要一个真正的随机数,您可以从天气或其他自然来源中提取数据,而不是从随机数生成器中提取数据。

  • 大多数随机数生成器确实会生成良好的均匀分布。它们只是不是随机的;而是随机的。问题是它们是经过计算的,因此您可以猜测序列中给定足够数量的下一个数字(这一事实使它们不利于需要真正随机数的安全性)。对于游戏和其他东西,你应该没问题。 (8认同)
  • 我很确定 OP 正在询问有关 C++ &lt;random&gt; 标头中提供的设施的具体信息。这个答案甚至没有涉及编程,更不用说 C++ 了。 (7认同)