使用连续种子生成统一的随机数?
Posted
技术标签:
【中文标题】使用连续种子生成统一的随机数?【英文标题】:Using continuously seed to generate uniform random numbers? 【发布时间】:2014-06-29 14:54:07 【问题描述】:我有一个有趣的问题,即
通过在标准库(或任何其他随机生成器)中使用著名的 mersenne twister std::mt19937 r
并将其设置为 r.seed(4)
的种子,例如,可以获得均匀随机生成的数字(在范围 @ 987654324@提供)。
如果我们从 1 到 100 循环遍历种子并生成第一个随机数,究竟会发生什么,这个序列是否仍然均匀分布?
for(int i = 0;i<100;i++)
r.seed(i);
int v = r();
我有一些算法,通过使用这个技巧而不是以通常的方式生成数字(无需每次都重置种子),它会更容易实现。
我实际上不相信通过像这样滥用生成器,可以再保持序列的一致性。
有没有人有专业知识可以对此进行推理?
非常感谢!
【问题讨论】:
这将是 100 个完全确定的数字。在这种情况下,“统一”是什么意思? Mersenne twister 随机数引擎:一种伪随机数生成引擎,可在闭区间 [0,2w-1] 内生成无符号整数。该引擎使用的算法经过优化,可以计算范围内几乎均匀分布的大量数字(例如在蒙特卡洛实验中)。 cplusplus.com/reference/random/mersenne_twister_engine 假设您的来源是正确的,并且生成的输出或多或少是均匀分布的,如果您继续重置状态,您到底为什么认为这个属性会成立?您是否意识到在生成结果时使用了先前的状态?无论如何,为什么还要涉及 PRNG?创建一个测试程序,在其中使用 [0,100) 范围内的每个整数为 mt19937 播种一次,生成一个随机数,并记下结果。然后将它们粘贴到一个数组中并在您的实际应用程序中使用它。 我认为该属性不会成立,这就是我所说的,但无论如何如果它会(我不知道)我的算法要快得多,因为我可以使用它仍然保持一致的事实分布式 【参考方案1】:这段代码按照你说的做,在每个数字生成之间重置种子:
#include <iostream>
#include <random>
int main ()
std::mt19937 r;
for(int i = 0;i<10;i++)
r.seed(i);
int v = r();
std::cout << v << std::endl;
return 0;
这个程序的输出是确定性的。您不断重置每一代之间的状态(并且此状态用于生成下一个随机数)。您绝对不能保证从不同梅森序列生成的数字的分布或均匀性(同样,每次重置种子时都会启动一个新序列)。
如果您的目标是生成限制在区间内的均匀分布,请使用std::uniform_real_distribution
:
Example from en.cppreference.com:
#include <random>
#include <iostream>
int main()
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<> dis(1, 2);
for (int n = 0; n < 10; ++n)
std::cout << dis(gen) << ' ';
std::cout << '\n';
它在 C++ 标准中定义,§ 26.5.8.2.2 部分:
uniform_real_distribution 随机数分布产生随机 数 x , a ≤ x
【讨论】:
以上是关于使用连续种子生成统一的随机数?的主要内容,如果未能解决你的问题,请参考以下文章