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
Random number generation in C++11: how to generate, how does it work?
提问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 forstd::mt19937
touint32_t
on x64, eventually this should be fixed and you can sayMyRNG::result_type seed_val
and thus make the engine very easily replaceable.
回答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.
通常,如果你想要一个真正的随机数,你会从天气或其他一些自然来源而不是随机数生成器中提取数据。