三个有符号整数的哈希函数

Hashing Function for Three Signed Integers

本文关键字:整数 哈希 函数 符号 三个      更新时间:2023-10-16

我正在尝试使用一个带有三个有符号整数的unsodered_map作为密钥(这是因为我希望使用tbb的concurrent_unordered_map)。

我把这个小(3x16位=>64位)函数放在一起:

// to hash
int64_t result = int16_t(x);
result = int64_t(result << 16) + int16_t(y);
result = int64_t(result << 16) + int16_t(z);
// from hash
int16_t x_ = int16_t(result >> 32);
int16_t y_ = int16_t(result >> 16);
int16_t z_ = int16_t(result & 0xFFFF);

这不起作用,我在这里犯了什么错误?

我的数字分布是这样的,接近零的负数或正数更有可能(通常小于+/-2^8),但我想将其扩展到2^32的范围,而不是这里的2^16示例。理想情况下,我正在寻找在典型范围内很少的碰撞,最好是一个简单的算法。有什么建议吗?

您的问题是执行位操作并添加有符号的数字。如果数字是负数,加法运算将转化为减法运算。在这种情况发生后,很难找出正确的原始值。

考虑:

int16_t x = -1, y = 2, z = -3;
int64_t result = x;          // result: FFFFFFFFFFFFFFFF
result = (result << 16) + y; // result: FFFFFFFFFFFF0000 + 0002
result = (result << 16) + z; // result: FFFFFFFF00020000 - 0003
return result;               // result: FFFFFFFF0001FFFD

因此,在保留了-1-3的同时,减法的结果已经将2减少为1

相反,您应该限制对无符号值的操作。对于无符号值,+|在代码中是等效的,因为您要将其添加到要填充0的数字部分中。

int64_t hash () {
    uint64_t result = uint16_t(x_);
    result = (result << 16) + uint16_t(y_);
    result = (result << 16) + uint16_t(z_);
    return result;
}