c++ - 三个有符号整数的哈希函数

标签 c++ hash

我正在尝试使用带有三个带符号整数的 unordered_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;
}

关于c++ - 三个有符号整数的哈希函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26348301/

相关文章:

C++ 类(公共(public)、私有(private)和 protected )

c++ - 从 QML 获取实际 View 大小

perl - 在 Perl 中取消引用哈希值的哈希值

java - 通过 Java 访问 GPU 进行加盐哈希

c++ - 为什么 std::hash 不能保证是确定性的?

java - 在HashSet中插入对象的条件?

c++ - 查找未使用的函数声明的工具?

c++ - 三元运算符作为命令?

C++ OBJ文件解析器

perl - 从第一个键到最后一个(Perl)对哈希进行排序