我最近发现了在C++11中生成随机数的新方法,但无法消化我读到的关于它的papers (那个引擎是什么,数学术语,比如分布,“其中产生的所有整数的可能性都是相等的”)。
所以有谁能解释一下
你可以在一个关于随机数生成的常见问题中调用它。
发布于 2011-08-19 05:41:23
这个问题太宽泛了,无法给出一个完整的答案,但让我挑选几个有趣的观点:
为什么是“同等可能性”
假设您有一个简单的随机数生成器,它以相等的概率生成数字0、1、...、10 (可以将其视为经典的rand()
)。现在你想要一个0,1,2范围内的随机数,每个随机数的概率相等。您的下意识反应将是使用rand() % 3
。但是等等,余数0和1比余数2出现得更频繁,所以这是不正确的!
这就是为什么我们需要适当的分布,它接受一个均匀随机整数的来源,并将它们转换为我们想要的分布,就像示例中的Uniform[0,2]
。最好把它留给一个好的库!
引擎
因此,在所有随机性的核心是一个好的伪随机数生成器,它生成一个在特定间隔内均匀分布的数字序列,并且理想情况下具有非常长的周期。rand()
的标准实现通常不是最好的,因此有一个选择是很好的。线性一致和Mersenne twister是两个很好的选择( rand()
实际上也经常使用LG);同样,让库处理它也很好。
它是如何工作的
简单:首先,设置一个引擎并播种它。种子完全决定了整个“随机”数字序列,因此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);
}
现在我们可以创建发行版了:
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使用引擎创建随机数!
while (true)
{
std::cout << uint_dist(rng) << " "
<< uint_dist10(rng) << " "
<< normal_dist(rng) << std::endl;
}
并发性
比起传统的rand()
,更倾向于<random>
的另一个重要原因是,现在如何让随机数生成线程安全变得非常清楚和明显:要么为每个线程提供自己的线程本地引擎,在线程本地种子上播种,要么同步对引擎对象的访问。
其他
codeguru.
result_type
,这是用于种子的正确整数类型。我想我曾经有一个错误的实现,这迫使我强制std::mt19937
的种子在x64上为uint32_t
,最终这应该被修复,你可以说MyRNG::result_type seed_val
,从而使引擎非常容易be发布于 2011-08-19 05:04:59
随机数生成器是一个方程,给定一个数字,它会给你一个新的数字。通常,您可以提供第一个数字,也可以从系统时间之类的内容中提取。
每次您请求一个新的数字时,它都会使用以前的数字来执行等式。
如果随机数生成器倾向于比其他数更频繁地生成相同的数,则它被认为不是很好。也就是说,如果你想要一个介于1和5之间的随机数,并且你有这样的数字分布:
2比其他数字生成的频率要高得多,因此它比其他数字更有可能生成。如果所有的数字都是一样的,那么你每次都有20%的机会得到每个数字。换句话说,上面的分布是非常不均匀的,因为2是受欢迎的。所有20%的分布将是均匀的。
通常,如果你想要一个真正的随机数,你应该从天气或者其他自然资源中提取数据,而不是从随机数生成器中提取数据。
https://stackoverflow.com/questions/7114043
复制相似问题