目前Boost具有hash_combine函数,该函数输出32位无符号整数(确切地说,size_t)。一些参考文献:
http://www.boost.org/doc/libs/1_43_0/doc/html/hash/reference.html#boost.hash_combine
http://www.boost.org/doc/libs/1_43_0/doc/html/hash/combine.html
Magic number in boost::hash_combine
我想探讨如何创建64位版本的hash_combine。
第一件事是获得黄金比例或任何其他无理数的64位。
第二部分是使用轮班。这部分相当棘手,我想询问是否有最佳实践或指导使用转移来获取哈希值?或者像原始代码一样选择班次:
seed ^= hash_value(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
是完全随意的吗?
另外,如何评估hash_combine
的输出以确保它不会产生比原始哈希函数hash_value
更多的冲突?
答案 0 :(得分:3)
如果你只想要一个散列2个64位值的hash_combine,并且你不需要一个新的字符串哈希函数,你可以从CityHash中提取一小部分代码,就像这样(假设size_t是一个64位无符号整数,添加你最喜欢的预处理器或模板技巧来验证):
template <class T> inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
const std::size_t kMul = 0x9ddfea08eb382d69ULL;
std::size_t a = (hasher(v) ^ seed) * kMul;
a ^= (a >> 47);
std::size_t b = (seed ^ a) * kMul;
b ^= (b >> 47);
seed = b * kMul;
}
(我认为在此处和其他地方复制此片段是可以的,因为它不构成CityHash代码的重要部分,但请查看CityHash来源和许可协议以确定自己)
答案 1 :(得分:2)
阅读http://burtleburtle.net/bob/hash/doobs.html以获取有关哈希函数设计的一些基本信息,以及http://burtleburtle.net/bob/hash/中的其他文章以获取更多详细信息。 CityHash已使用http://code.google.com/p/smhasher/进行了测试,您可以使用相同的测试套件测试hash_combine
。
虽然我不是哈希专家,但最近哈希函数的设计让我相信2档技术提升的hash_combine()
使用不再是最先进的,可以改进上。
答案 2 :(得分:0)
boost::hash_combine
并非完全随机,它甚至分布也不均匀或particularly good。
组合两个散列的一种好方法是首先确保两个散列分布均匀,然后可以将两个散列与xor组合。为确保它们分布均匀,请使用good integer hash function。
将所有内容放在一起:
uint64_t xorshift(const uint64_t& n,int i){
return n^(n>>i);
}
uint64_t hash(const uint64_t& n){
uint64_t p = 0x5555555555555555; // pattern of alternating 0 and 1
uint64_t c = 17316035218449499591ull;// random uneven integer constant;
return c*xorshift(p*xorshift(n,32),32);
}
uint64_t hash_combine(const uint64_t& seed, const uint64_t& v) {
uint64_t c = 17316035218449499591ull;// random integer constant;
return hash(v)^(seed+c);
}
如果散列的分布不能满足您的目的,则只需对值进行双散列,例如:hash(hash(v))^seed