【问题标题】:Hashing Function for Three Signed Integers三个有符号整数的散列函数
【发布时间】:2014-10-14 05:05:53
【问题描述】:

我正在尝试使用以三个有符号整数作为键的 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 示例。理想情况下,我正在寻找典型范围内的极少碰撞,最好是一个简单的算法。有什么建议吗?

【问题讨论】:

  • 怎么不行?

标签: c++ hash


【解决方案1】:

您的问题是您正在执行位操作并添加有符号数字。如果数字为负数,则加法运算将转换为减法。之后就很难梳理出正确的原始值。

考虑:

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;
}

【讨论】:

    猜你喜欢
    • 2010-12-21
    • 1970-01-01
    • 2017-05-02
    • 1970-01-01
    • 2010-10-14
    • 2016-02-14
    • 2013-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多