C ++标准(从C ++ 11一直到当前的C ++ 17草案)在[rand.eng.lcong]中说明如下:
template<class Sseq> explicit linear_congruential_engine(Sseq& q);
效果:构造一个
linear_congruential_engine
对象。使用 k =⌈log 2 ( m )÷32⌉和 a 数组32(或等效)长度 k + 3,调用q.generate(a + 0, a + k + 3)
然后计算 S =(Σ j = 0 < sup> k -1 a j +3 ·2 32 j )mod m 。如果 c mod m 为0且 S 为0,则将引擎状态设置为1,否则将引擎状态设置为S.
为什么 a 0 , a 1 和 a 2 丢弃?
答案 0 :(得分:1)
这是我一直想弄清楚的事情。我有一个假设,但没有真正的证据。但是,规则起源于(N2079由@ T.C.链接的)的文件证实了我理论的一部分。
请注意,规则来自的函数接受文档中的std::seed_seq
对象,而不是模板化类。这意味着在编写规则时,它是专门为std::seed_seq
而制定的,而不是一般的SeedSequence的概念。这意味着我们可以查看std::seed_seq
类以获取有关此信息的信息,特别是std::seed_seq::generate
的定义方式。
std::seed_seq::generate
使用的方法已得到很好的解释on cppreference.com。它有点复杂,但可以分为4个阶段。
使用一些初始数据初始化输出范围(我在这里包括k=0
)
将原始种子数据移至输出范围(k=1..s
)
将种子数据扩展到输出范围的其余部分(k=s+1..m-1
,其中m=max(s+1, n)
)
随机输出范围内的数据(k=m..m+n-1
)
当使用modulo&lt; = 2 32 (包括std::linear_congruential_engine
和std::minstd_rand
)播种std::minstd_rand0
时,它只需要生成1个值来自std::seed_seq
,但是根据此规则,它会生成4.因此,当将n
从1更改为4时,此算法会发生什么变化?
改变的一个部分是改组阶段从1次迭代变为4.由于std::seed_seq
的目标之一是产生高质量的播种值“给定小种子或分布不均的初始种子序列。 `,这些额外的混洗迭代可能会改善结果的种子值。它之所以丢弃前3个值而不是最后一个值的原因是因为后面的值(通常)是更多的混乱值。
值得注意的是,所有4个阶段的关键等式是值begin[k]^begin[k+p]^begin[k−1]
(在最后阶段将XOR替换为加法)。在n=1
时,这只会变为begin[k]
(或最后一个阶段的3*begin[k]
)(请注意,“输出范围begin[x]
的索引采用模n”和{{ 1}})。当x % 1 == 0
时,此等式更符合预期,这有助于更有效地改变数据。
所以简短的回答是n=4
丢弃由种子序列生成的3个数字,因为std::linear_congruential_engine
生成这些数字可以提高实际使用的值的质量。现在,在定义SeedSequence的通用概念之前决定丢弃生成器中的这些数字,因此在生成器中解决问题更有意义,而不是使种子序列类过于复杂。但是,现在这意味着将丢弃由任何种子序列生成的前3个值。这是否值得,这可能是值得商榷的,但现在就是这样。