Algorithm 散列函数分布在n个值上(带扭曲)
我想知道是否有任何散列函数可以将输入分布到n个值上。当然,分布应该相当均匀。但有一个转折点。对于n的小变化,很少有元素会得到新的散列。最佳情况下,它应该在n个值上均匀地分割所有k,如果n增加到n+1,则只有k/n-k/(n+1)值必须移动到新哈希中均匀分布。很明显,有一个简单地创建统一值然后修改的散列可以工作,但是这会移动大量散列来填充新节点。这里的目标是尽可能少的值落在一个新的存储桶中。假设2^{n-1}Algorithm 散列函数分布在n个值上(带扭曲),algorithm,hash,Algorithm,Hash,我想知道是否有任何散列函数可以将输入分布到n个值上。当然,分布应该相当均匀。但有一个转折点。对于n的小变化,很少有元素会得到新的散列。最佳情况下,它应该在n个值上均匀地分割所有k,如果n增加到n+1,则只有k/n-k/(n+1)值必须移动到新哈希中均匀分布。很明显,有一个简单地创建统一值然后修改的散列可以工作,但是这会移动大量散列来填充新节点。这里的目标是尽可能少的值落在一个新的存储桶中。假设2^{n-1}
编辑:添加了mix()函数,以对每个n的散列进行不同的混合,否则当n不是素数时会出现不一致性。Hmm,我在实现这一点时遇到了一些困难。假设n是10,这使得n4(2^3=8<10<2^4=16)。然后我计算H(v),在本例中,Pythons内置哈希函数,返回64位哈希。我只保留前4位(请记住,这会使一些负数变为正数)。但是堆栈崩溃,因为H(v)的哈希不一定比v的哈希小。您是否考虑了某个H?进行了更多测试,并在移动H(v)后每次运行时(再次将一些负数变为正数)它似乎都会起作用。我认为这可能与Python如何进行散列和负数有关(必须做一个变通方法,以实际获得n个前位,而不是让数字变为负数)做了更多的测试,您的第三个属性似乎是错误的。在我的测试中,1000个条目从16个节点到17个节点,最终有945个更改。从32个节点到33个节点,我做了973个更改。因此,它似乎实际上更接近所有数据,必须重新验证。@PMunch我认为您一定误解了一些非常严重的内容。您不应该这样做我不确定你关于“将一些否定变为积极”的评论是什么意思,但我们应该在这里谈论未签名的数字——没有否定。@PMunch啊,我打赌这里的罪魁祸首是Python的(有点漂亮)为整数选择哈希函数:即标识函数。基本上使用任何其他哈希函数,效果会更好;例如,
hash(str(x))
。Python不是我最擅长的语言,但请耐心等待,我很快会发布一些代码并进行一些分析。
import math
def ilog2(m): return int(math.ceil(math.log(m,2)))
def hash_into(obj, N):
cur_hash = hash(obj)
mask = pow(2, ilog2(N)) - 1
while (cur_hash & mask) >= N:
# seems Python uses the identity for its hash on integers, which
# doesn't iterate well; let's use literally any other hash at all
cur_hash = hash(str(cur_hash))
return cur_hash & mask
def same_hash(obj, N, N2):
return hash_into(obj, N) == hash_into(obj, N2)
def bump_stat(objs, N):
return len([obj for obj in objs if same_hash(obj, N, N+1)])
alphabet = [chr(x) for x in range(ord('a'),ord('z')+1)]
ascending = alphabet + [c1 + c2 for c1 in alphabet for c2 in alphabet]
def main():
print len(ascending)
print bump_stat(ascending, 10)
print float(bump_stat(ascending, 16))/len(ascending)
# prints:
# 702
# 639
# 0.555555555556
Let H(k) be the hash of k.
int hash = H(k);
for (int n=N-1;n>0;--n) {
if ((mix(hash,n) % (i+1))==0) {
break;
}
}
//put it in node n