Hash “的函数”;“均匀分布”;可能值空间中的连续数字

Hash “的函数”;“均匀分布”;可能值空间中的连续数字,hash,sequential,Hash,Sequential,我需要在GoogleAppEngine(或者你可以想到任何其他哈希表)中的键下存储一组实体,我需要从顺序输入创建自己的键 例如,假设我只处理长度为一个十进制数字的键。然后我需要为键“0”存储一个实体,为键“1”存储一个实体,为键“2”存储一个实体,以此类推 问题是,如果我直接使用这个递增序列作为键,它将导致所有实体在物理上彼此非常接近,这可能会导致严重的性能问题。对于一般的哈希表,您可以认为所有条目不是均匀分布在所有存储桶中,而是聚集在几个存储桶中,这也会导致查找等性能下降 因此,我正在寻找一些

我需要在GoogleAppEngine(或者你可以想到任何其他哈希表)中的键下存储一组实体,我需要从顺序输入创建自己的键

例如,假设我只处理长度为一个十进制数字的键。然后我需要为键“0”存储一个实体,为键“1”存储一个实体,为键“2”存储一个实体,以此类推

问题是,如果我直接使用这个递增序列作为键,它将导致所有实体在物理上彼此非常接近,这可能会导致严重的性能问题。对于一般的哈希表,您可以认为所有条目不是均匀分布在所有存储桶中,而是聚集在几个存储桶中,这也会导致查找等性能下降

因此,我正在寻找一些函数,以便在可用值空间中更均匀地“重新分配”我的值

为了继续使用单个数字键的示例,我可以创建一个包含所有可能值的随机排列的表,如[5,9,2,4,1,8,0,6,3,7],并将其索引到该表中。然后,当我存储条目0、1和2时(它们将彼此相邻),我会分配更多分布在服务器或散列桶中的键5、9和2

但是我需要找到一种方法来处理156位的数字,在这种情况下,一个包含所有值的随机排列的表是不可行的

我有两个要求:

  • 每一个可能的156位数字必须映射到正好一个值(最多160位是可以的)。不允许碰撞
  • 这在计算上应该很便宜

我找到了一种方法:简单地用密码或其他160位密码“加密”我的值。但对于我试图实现的目标来说,这似乎是太多的计算工作了。是否有一些伪随机函数可以用我的值作为种子?它们能保证无冲突吗?

您可以使用离散对数,它为您的所有数组位置提供完美的确定排列。但是,排列是单向的:如果不诉诸暴力(或在允许的方向上重新排列),就无法检索新的第i个数组位置的原始位置

如果您不关心额外的空间,您可以存储成对的
,并完全随机地放置它们(使用一些PRNG函数),以防碰撞(或注意已使用的位置)。现在,这些对被均匀地分布。检索第i个元素需要O(N),其中N是位置数。这就是这个算法的价格

只取156位值中的几个随机位,并使用它们形成一个12位无符号索引。使用此索引从最终空间中选择第k个存储桶(您的空间被划分为2^12个存储桶)。只有当它们共享相同的12位随机位时,值才会趋向于聚合,如果您仔细挑选它们,这是非常不可能的。。。使用剩余的156-12=143位偏移铲斗内部


创建一个固定的156位随机排列。

我在想,但是用156位数字进行排列听起来比SHACAL更难(也就是说更慢)。。。还是有什么把戏?(无法检索原始值是可以的)不幸的是,任何标准哈希函数都会受到冲突的影响,这是最好的鸽子原则:-)数组有多大?156位值输入,最多160位值输出。因此,唯一的映射肯定是可能的。我的答案中增加了另一个解决方案:)不幸的是,我确实关心空间。。。这就是160位限制的来源(除了我需要存储的156位之外,没有额外的字节),让我们假设您希望对0到255之间的数字执行此操作。以下是值“number”:“hash”0:0、1:128、2:64、3:192、4:32、5:96、6:160、7:224,这就是你想要的吗?@OndrejPetrzilka,基本上颠倒了数字中位的顺序?我们在下面G_G的回答中讨论了这个想法。我认为这可能是一个有用的方法,只是还没有时间去完成它。。。