【问题标题】:Fair assumptions about std::hash implementations关于 std::hash 实现的公平假设
【发布时间】:2018-12-13 13:43:43
【问题描述】:

我们在研究数据库项目中使用多种形式的散列。例如,对于基数聚类,我们使用 n 个最低有效位来确定聚类 ID。我们使用std::hash 进行哈希,这对我们来说已经足够了。

然而,虽然我们知道大多数实现使用标识来散列整数,但我们偶然发现浮点散列(这是否有意义是另一个讨论)在不同平台上的实现方式不同。

我们可以对std::hash 做出任何公平的假设吗?

MacOS: clang version 6.0.1 (tags/RELEASE_601/final) std::hash<float>{}(1.0f): 0000000000000000000000000000000000111111100000000000000000000000 std::hash<double>{}(1.0): 0011111111110000000000000000000000000000000000000000000000000000

Ubuntu: clang version 6.0.0-1ubuntu2 (tags/RELEASE_600/final) std::hash<float>{}(1.0f): 0101001111100101011001010000100100010100111101010010111101001101 std::hash<double>{}(1.0): 0111010001100001101001000101000001001110110011100111101110011011

【问题讨论】:

  • 如果你这么担心,为什么不拥有自己的哈希函数呢?
  • 所以澄清一下,您要问的是,std:hash 是否希望在这种情况下跨平台给出一致的答案,如果是,承诺什么?
  • @ShafikYaghmour:是的。

标签: c++ hash std floating


【解决方案1】:

您可以假设的唯一内容由标准定义(请参阅cppreference)。

这意味着:

特别是,他们定义了一个 operator() 常量:

  1. 接受一个 Key 类型的参数。

  2. 返回一个 size_t 类型的值,表示参数的哈希值。

  3. 调用时不抛出异常。

  4. 对于两个相等的参数 k1 和 k2,std::hash()(k1) == std::hash()(k2)。

  5. 对于两个不同的参数 k1 和 k2 不相等,std::hash()(k1) == std::hash()(k2) 应该的概率 非常小,接近 1.0/std::numeric_limits::max()。

因此,您可以在不同平台上、在具有不同编译器版本的同一平台上、甚至从一次运行到另一次运行时获得不同的值。就您而言,似乎在一种情况下您可能正在使用 libc++,而在另一种情况下,您可能正在使用 libstdc++。

【讨论】:

    猜你喜欢
    • 2018-02-03
    • 1970-01-01
    • 2018-11-08
    • 1970-01-01
    • 2016-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-30
    相关资源
    最近更新 更多