[英]Generating millions of non-repeating random numbers in Java
我有一个问题,我可以使用什么算法在 Java 中生成一组 2^21 个随机唯一数? java 中是否还有另一个库可以生成除了 math.random 的随机数?
提前致谢!
Take a look at Apache Commons Math API's random pacakge http://commons.apache.org/math/userguide/random.html
关键问题是“数字”是什么意思?
一般来说,这个问题可以通过“生成一个数字列表,将其随机排列,取其中的前 2^21 个”来解决。第一部分是微不足道的 第二部分可以通过 Fisher yates 算法解决 真正的问题是如果你想使用非常大的数字空间。 那么你需要一个懒惰的解决方案
这是我要做的:使用数据结构来表示列表,该列表外观看起来像一个数组,但在内部使用基于散列表的稀疏数组表示。 此外,如果在尝试从单元格中读取数据时,如果您没有在 hash 中找到任何内容,则只需返回该单元格的索引即可。
您修改后的 Fisher yates 在 2^21 处停止index
变量,并在index
和数组的“长度”(整数个数)之间使用随机变量j
这种惰性方法会在 O(n) 时间和 O(n) 空间内生成任何类型数字的随机非重复列表,其中 n 是您尝试生成的数组的长度。 这是你能做的最好的。
有关 Fisher-Yates http://en.wikipedia.org/wiki/Fisher-Yates_shuffle的解释
您可以使用Format-Preserving Encryption来加密计数器。 您的计数器只是从 0 向上,加密使用您选择的密钥将其转换为您想要的任何基数和宽度的看似随机的值。
块密码通常具有固定的块大小,例如 64 或 128 位。 但是 Format-Preserving Encryption 允许您采用像 AES 这样的标准密码,并使用您想要的任何基数和宽度(例如问题参数的基数 2,宽度 21)制作更小宽度的密码,算法仍然是加密健壮。
保证永远不会发生冲突(因为密码算法创建 1:1 映射)。 它也是可逆的(2 路映射),因此您可以获取结果数字并返回您开始使用的计数器值。
AES-FFX是一种建议的标准方法来实现这一点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.