- 使用最大线性反馈移位寄存器 - 如果我理解正确,它只生成递增顺序的数字,而且并没有覆盖整个范围。
- 使用Fisher-Yates或其他集合洗牌算法 - 鉴于大范围的限制,这将违反内存限制。
- 维护类似集合的收集,并继续生成随机整数(可能使用
Random
),直到不重复为止,即不在集合中 - 除了可能无法满足内存要求外,当生成序列中的最后几个数字时,它会变得非常缓慢。 - 32位随机排列,但我想不出确保不可重复性的方法。
有没有其他方法来看待这个问题 - 也许利用固定值范围的优势 - 以满足内存要求的解决方案?也许.NET类库带有一些有用的东西吗?
更新1
感谢大家对解决方案的见解和创意建议。我将尽快实施和测试这里提出的2或3个最有前途的解决方案(包括正确性和内存效率),并发布结果,然后选择一个“获胜者”。
更新2
我尝试了hvd在下面的评论中提出的建议。我尝试使用.NET中的BitArray
和我的自定义实现,因为.NET的限制为int.MaxValue
条目,不足以覆盖整个整数范围。
我很喜欢这个想法的简单性,如果它运行良好,我愿意“牺牲”那512 MB的内存。不幸的是,在我的计算机上生成下一个随机数需要花费相当长的时间,甚至多达十几秒钟,我的计算机配备了3.5 GHz的Core i7 CPU。因此,如果您需要生成许多随机数,这是不可接受的。我想这是可以预测的,如果我没有弄错的话,它是O(M x N)算法,其中N是2 ^ 32,M是请求的整数数量,因此所有这些迭代都会付出代价。
理想情况下,我希望在满足内存需求的同时以O(1)时间生成下一个随机数,也许这里建议的下一个算法适合此目的。我会尽快尝试它们。
更新3
我刚刚测试了线性同余生成器,我可以说我对结果感到非常满意。它看起来是本主题中胜者的有力竞争者。
正确性:所有生成的整数仅一次(我使用了位向量来检查这一点)。
随机性:相当不错。
内存使用: 极佳,仅使用了少量字节。
运行时间: 生成下一个随机整数非常快,正如你从O(1)算法所期望的一样。在我的机器上,生成每个整数总共花费了大约11秒钟。
总体而言,如果您不需要高度随机化的序列,我认为这是一种非常适当的技术。
更新4
下面描述的模 multiplicative inverse technique 和 LCG 技术表现非常相似 - 这并不奇怪,因为两者都基于模算术 - 尽管我发现实现起来有点不那么直接,以产生令人满意的随机序列。
我发现有趣的一个区别是,这种技术似乎比LCG更快:生成整个序列大约花费了8秒钟,而LCG则是11秒钟。除此之外,所有关于内存效率、正确性和随机性的评论都是一样的。
更新5
看起来用户TomTom在我指出Mersenne Twister生成重复数字的问题后没有通知地删除了他们的回答。所以我猜这完全排除了Mersenne Twister。
更新6
我测试了另一种被建议的技术Skip32,虽然我真的很喜欢它产生的随机数的质量,但是该算法无法在可接受的时间内生成整个范围的整数。因此,与能够完成该过程的其他技术相比,它不足。顺便说一下,我使用了这里的C#实现——我将代码更改为只进行一轮,但它仍然无法及时完成。
综上所述,根据上述结果,我个人选择的解决方案是模数乘法逆元技术,紧随其后的是线性同余发生器。有些人可能会认为这在某些方面比其他技术劣,但考虑到我的原始限制,我认为它最适合。