激活梅森旋转算法伪随机数生成器

8

似乎有一些关于使用mt19937的神话,具体来说,一旦种子确定,应该忽略由生成器产生的“某些”位数,以尽可能接近伪随机。

我见过的代码示例如下:

boost::mt19937::result_type seed = 1234567; //taken from some entropy pool etc
boost::mt19937 prng(seed);
boost::uniform_int<unsigned int> dist(0,1000);
boost::variate_generator<boost::mt19937&,boost::uniform_int<unsigned int> > generator(prng,dist);

unsigned int skip = 10000;
while (skip--)
{
   generator();
}

//now begin using for real.
....

我的问题是:

  1. 这是神话还是有一些真相?

  2. 如果它是可行的,应该忽略多少位?因为我看到的数字似乎是随意的。


6
这个人似乎在暗示这不是一个神话:http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html -- 如果我理解正确,一个龙卷风需要“一些时间”来清除起始状态中的初始零,如果你使用一个大部分为零的初始状态(例如,只有一个32位的值,让twister的大部分状态都为零),则产生的值将是“不够随机的”(或者说与种子具有低海明距离的其他值太相似)。这篇文章仅仅比维基百科多了一点点研究,所以请谨慎参考。 - Yakk - Adam Nevraumont
@Yakk 有趣的是,似乎所有这些我不断看到的玄学都有一些“东西”存在。 - user1781730
1
无论真假或所需迭代次数,正确的解决方案不是从熵池中填充整个种子的随机比特,而不仅仅是填充前32位或任何其他比特吗? - hyde
Gilly:这个问题与Java有什么关系? - Sebastian Mach
1个回答

4

第一条评论中提到的论文Mersenne Twister with improved initialization,不仅是某个人写的,而且他是基于该论文的Boost实现的两位共同作者之一。

使用单个32位整数(4字节)作为此生成器的种子的问题在于,根据Boost文档,生成器的内部状态为2496字节。这样一个小的种子需要一段时间才能传播到生成器的其余内部状态,特别是因为Twister并不意味着具有加密安全性。

为了解决您关于需要运行一段时间才能启动生成器的担忧,您需要使用备用(明确的)构造函数。

template<typename SeedSeq> explicit mersenne_twister_engine(SeedSeq &);

这是第三条评论的精神,其中您使用比单个整数更长的内容进行初始化。提供的序列来自某个生成器。要使用熵池,请编写一个生成器作为从熵池适配器返回所需值的方式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接