我必须基于3个短裤创建一个哈希函数。这样做的最佳方法是什么?
编辑 我有一个名为Point的对象。它由三个短路(x,y,z)组成。为了在QSet中使用这个对象,我必须填写以下函数的主体
uint qHash(const Point &point) {
// return something here that is a unique combination of x, y, z so that
// it is very quick to calculate and has minimal (if any) hash collisions
}
答案 0 :(得分:2)
这很大程度上取决于您对哈希函数的需求。
速度是否至关重要?
近乎完美的哈希分布是否至关重要?
您的哈希密钥必须有多大? 32位? 64位?更大?
如果不了解任何其他细节,您可能需要考虑以下几点:
uint hash = (31 * 31 * 31 * (uint)short1) ^ (31 * 31 * (uint)short2) ^ (31 * short3);
这将是快速的,并且应该具有合理的位分布,即使短路的输入值没有很好地分布
<强>更新强>
修改代码示例以键入uint
。如果输入在0到512范围内,我的变体应该可以正常工作。
如果您有兴趣了解为什么我将每个输入乘以31的幂,请参阅
Why does Java's hashCode() in String use 31 as a multiplier?
答案 1 :(得分:1)
如果三条短裤分布相对均匀,您可以使用以下内容:
hashVal = (short1 xor short2 xor short3) modulo numBuckets
这会缩短您的时间,缩短到0
到numBuckets - 1
的特定范围。
这是否合适取决于您的输入值将如何分配以及您对散列函数的期望。
基于你的问题编辑声明散列必须进入无符号整数,并假设一个16位短和32位无符号整数,没有办法完全避免冲突(你需要48位) 。一种可能性是使用:
hashVal = (x leftshift 16) logical-or (y leftshift 8) logical-or (z)
这将合并(逻辑或)您的值:
xxxxxxxxxxxxxxxx0000000000000000
yyyyyyyyyyyyyyyy00000000
zzzzzzzzzzzzzzzz
并且至少可以降低相互影响的x/y/z
值的可能性。
并且,继续你的评论:
我希望我的输入值在0到512的范围内。这会如何影响我的决定?
如果您的输入值被限制在0到512(含)范围内,则每个输入值只需要10位(这将为您提供值0到1023)。在这种情况下,其中三个很容易适合32位无符号整数,因此您可以使用:
hashVal = (x leftshift 20) logical-or (y leftshift 10) logical-or (z)
这提供了完美的哈希,绝对没有碰撞的可能性。