从一组中的2个数字的组合生成非碰撞随机数?

时间:2016-03-08 01:33:30

标签: algorithm data-structures language-agnostic statistics bits

我有一组长度为> = 2的64位无符号整数。我从该集合中挑选2个随机整数ab。我应用确定性操作将ab合并到不同的64位无符号整数c_1c_2c_3等。我添加{ {1}}到集合。我重复这个过程。

我可以使用什么程序来保证c_ns实际上永远不会与集合中的现有位串发生冲突,即使经过数百万步之后呢?

2 个答案:

答案 0 :(得分:2)

由于您从一对64位数字生成多个64位值,我建议您随机选择两个数字,并使用它们初始化一个64位xorshift随机数生成器,其中包含128位状态。有关示例,请参阅https://en.wikipedia.org/wiki/Xorshift#xorshift.2B

但是,当您使用多个随机数生成器时,很难预测碰撞概率。使用单个PRNG,经验法则是在生成范围的平方根后,您有50%的碰撞几率。例如,如果您生成32位随机数,则在生成大约70,000个数字后,您的碰撞概率将达到50%。平方根2 ^ 32是65,536。

使用单个64位PRNG,您可以生成超过10亿个随机数,而无需过多担心冲突。在您的情况下,您从可能较小的池中选择两个数字,然后初始化PRNG并生成相对较少的值,并将其添加回池中。在这种情况下,我不知道如何计算碰撞概率。

但是,请注意,无论碰撞的概率如何,碰撞的可能性始终存在。实际上发生了“十亿分之一”的机会:平均每十亿次运行该程序。最好将输出数保存在哈希集或其他不允许存储重复项的数据结构中。

答案 1 :(得分:1)

我认为在没有任何其他给定约束的情况下,您可以做的最好的事情是使用伪随机函数将两个64位整数映射到64位整数。根据{{​​1}}和a的顺序是否对您的问题很重要(例如b应映射到除(3, 5)之外的其他内容),您不应该或应该对它们进行排序之前。

将较大输入映射到较小输入的伪随机函数的自然选择是散列函数。您可以选择任何产生至少64位输出的哈希函数并截断它。 (在这种情况下,我最喜欢的是带有任意固定密钥的SipHash,它很快并且有许多语言的公共域实现,但你可能只使用任何可用的东西。)

birthday bound确定您在发生碰撞之前可以生成的预期数量,因为您实际上是在随机选择值。链接的文章包含64位值概率的表。例如,如果生成大约600万个条目,则碰撞概率为百万分之一。

我不认为在一般情况下可以击败这种方法,因为您可以在组合的元素序列中编码任意数量的信息,同时输出值中的信息量固定为64-位。因此,您必须考虑碰撞,随机函数在所有可能的序列中均匀分布概率。