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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7114043/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 16:29:06  来源:igfitidea点击:

Random number generation in C++11: how to generate, how does it work?

c++c++11random

提问by Kerrek SB

I recently came across new way to generate random numbers in C++11, but couldn't digest the papersthat I read about it (what is that engine, maths term like distribution, "where all integers produced are equally likely").

我最近遇到了在 C++11 中生成随机数的新方法,但无法消化我读到的有关它的论文(那个引擎是什么,数学术语如分布,“所有生成的整数的可能性相等”)。

So can anyone please explain

所以任何人都可以请解释

  • what are they?
  • what does they mean?
  • how to generate?
  • how do they work?
  • etc
  • 这些是什么?
  • 他们是什么意思?
  • 如何生成?
  • 它们是如何工作的?
  • 等等

You can call it all in one FAQ about random number generation.

您可以在一个关于随机数生成的常见问题解答中将其全部称为。

回答by Kerrek SB

The question is way too broad for a complete answer, but let me cherry-pick a couple of interesting points:

这个问题对于一个完整的答案来说太宽泛了,但让我挑选几个有趣的点:

Why "equally likely"

为什么“同样可能”

Suppose you have a simple random number generator that generate the numbers 0, 1, ..., 10 each with equal probability (think of this as the classic rand()). Now you want a random number in the range 0, 1, 2, each with equal probability. Your knee-jerk reaction would be to take rand() % 3. But wait, the remainders 0 and 1 occur more often than the remainder 2, so this isn't correct!

假设您有一个简单的随机数生成器,它以相等的概率生成数字 0、1、...、10(将其视为经典的rand())。现在您需要一个范围为 0、1、2 的随机数,每个数的概率相等。你的下意识反应是接受rand() % 3。但是等等,余数 0 和 1 比余数 2 出现得更频繁,所以这是不正确的!

This is why we need proper distributions, which take a source of uniform random integers and turn them into our desired distribution, like Uniform[0,2]in the example. Best to leave this to a good library!

这就是为什么我们需要适当的分布,它采用均匀随机整数的来源并将它们转换为我们想要的分布,就像Uniform[0,2]在示例中一样。最好把它留给一个好的图书馆!

Engines

引擎

Thus at the heart of all randomness is a good pseudo-random number generator that generates a sequence of numbers that uniformly distributed over a certain interval, and which ideally have a very long period. The standard implementation of rand()isn't often the best, and thus it's good to have a choice. Linear-congruential and the Mersenne twister are two good choices (LG is actually often used by rand(), too); again, it's good to let the library handle that.

因此,所有随机性的核心是一个良好的伪随机数生成器,它生成一个数字序列,这些数字在一定间隔内均匀分布,并且理想情况下具有很长的周期。的标准实现rand()通常不是最好的,因此有选择是件好事。Linear-congruential 和 Mersenne twiner 是两个不错的选择(LG 实际上也经常被 使用rand());再一次,让图书馆来处理是件好事。

How it works

这个怎么运作

Easy: first, set up an engine and seed it. The seed fully determines the entire sequence of "random" numbers, so a) use a different one (e.g. taken from /dev/urandom) each time, and b) store the seed if you wish to recreate a sequence of random choices.

简单:首先,设置引擎并为其播种。种子完全确定了“随机”数字的整个序列,因此 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);
}

Now we can create distributions:

现在我们可以创建分布:

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)

...And use the engine to create random numbers!

...并使用引擎创建随机数!

while (true)
{
  std::cout << uint_dist(rng) << " "
            << uint_dist10(rng) << " "
            << normal_dist(rng) << std::endl;

}

Concurrency

并发

One more important reason to prefer <random>over the traditional rand()is that it is now very clear and obvious how to make random number generation threadsafe: Either provide each thread with its own, thread-local engine, seeded on a thread-local seed, or synchronize access to the engine object.

更喜欢<random>传统的一个更重要的原因rand()是,现在如何使随机数生成线程安全变得非常清晰和明显:要么为每个线程提供自己的线程本地引擎,在线程本地种子上播种,要么同步访问到引擎对象。

Misc

杂项

  • An interesting articleon TR1 random on codeguru.
  • Wikipediahas a good summary (thanks, @Justin).
  • In principle, each engine should typedef a result_type, which is the correct integral type to use for the seed. I think I had a buggy implementation once which forced me to force the seed for std::mt19937to uint32_ton x64, eventually this should be fixed and you can say MyRNG::result_type seed_valand thus make the engine very easily replaceable.
  • codeguru 上一篇关于 TR1 随机的有趣文章
  • 维基百科有一个很好的总结(谢谢,@Justin)。
  • 原则上,每个引擎都应该 typedef a result_type,这是用于种子的正确整数类型。我觉得我有一个马车实现一次并逼我逼种子std::mt19937uint32_t在x64,最终这应该是固定的,你可以说MyRNG::result_type seed_val,从而使发动机很容易更换。

回答by N_A

A random number generator is a equation that, given a number, will give you a new number. Typically you either provide the first number or its pulled from something like the system time.

随机数生成器是一个方程,给定一个数字,它会给你一个新数字。通常,您要么提供第一个数字,要么从系统时间之类的东西中提取它。

Each time you ask for a new number it uses the previous number to execute the equation.

每次您要求输入新数字时,它都会使用先前的数字来执行等式。

A random number generator is not considered very good if it has a tendency to produce the same number more often than other numbers. i.e. if you wanted a random number between one and 5 and you had this distribution of numbers:

如果随机数生成器倾向于比其他数字更频繁地生成相同的数字,那么它就不会被认为是很好的。即,如果您想要一个介于 1 和 5 之间的随机数,并且您有以下数字分布:

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

2 is generated FAR more often than any other number, so it is more likely to be produced than other numbers. If all numbers were equally like you would have a 20% chance of getting each number every time. To say it another way, the above distribution is very uneven because 2 is favored. A distribution with all 20%'s would be even.

2 比任何其他数字更频繁地生成 FAR,因此它比其他数字更有可能被生成。如果所有数字都一样,您每次都有 20% 的机会获得每个数字。换句话说,上面的分布很不均匀,因为 2 是有利的。所有 20% 的分布将是均匀的。

Typically, if you want a true random number you would pull data from something like weather or some other natural source rather than a random number generator.

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