【问题标题】:hash( (-2,2) ) == hash( (2,-2) ) returns True (Python)hash( (-2,2) ) == hash( (2,-2) ) 返回 True (Python)
【发布时间】:2014-02-13 02:04:09
【问题描述】:

所以,这很有趣——众所周知,Python 的 hashhash(-1) == hash(-2)as discussed elsewhere 上返回 True,但是这个呢?

>>> hash( (-2,2) ) == hash( (2,-2) )
True

这是一个功能吗?

其他一些快速实验:

>>>(-2,2) == (2,-2)
False
>>>hash( (-1,) ) == hash( (-2,) )
True
>>>hash( (-1,-2) ) == hash( (-2,-1) )
True
>>>hash( (-2.01,2.01) ) == hash( (2.01,-2.01) )
False
>>>hash( (-1,1) ) == hash( (1,-1) ) 
False

【问题讨论】:

  • 那会是什么功能?我倾向于说它“显然”不是一个特性,因为你希望你的哈希函数不具有这些属性。你的问题是什么?
  • 顺便说一句,你可能打算写(-1,),因为额外的一对括号是多余的
  • 嗯,hash(-1) == hash(-2) 是一个功能,因为它不是一个错误,而且它是有原因的(上面的链接)。这是否有类似的解释 - 或者它只是一个奇怪的?这是我的问题。
  • 这不是错误,因为无法避免哈希冲突。它当然不是一个功能,只是一个解决方法/实现细节。它也很可能是依赖于实现的,所以它与 Python 关系不大,更多的是与 cpython 实现有关(你在 pypy 或 ironpython 中尝试过吗?)
  • @TomStephens 请查看我的答案以获得全面的解释。

标签: python hash


【解决方案1】:

这不是功能;这是一个巧合。发生哈希冲突。

Python 的 int 散列真的很笨,它的元组散列通常没问题。

Python 的 dict 实现旨在用糟糕的哈希值来解决问题,所以这并不重要。

【讨论】:

  • 巧合的是,我实际上只是在本周早些时候查看了 Python 进行元组哈希的方式,因为我正在考虑为 JSON 数据编写一个独立于实现/独立于语言的哈希。我觉得有点意思:hg.python.org/cpython/file/6e04027ed53e/Objects/…
【解决方案2】:

在查看哈希逻辑之前,让我们先看看一些花絮。

  1. python 整数的哈希值将是数字本身。

  2. 第 1 点的唯一例外是 -1。因为-1 在内部用于指示错误情况。因此,-1 的哈希值将是 -2。 (对于 -2 也只有 -2。)

有了这个理解,我们就可以回答你的例子2、3和5了。

示例2:-1的哈希值==-2的哈希值。所以,这是真的。

示例 3:同示例 2 的原因

示例 5:-1 和 1 的哈希值不同(分别为 -2 和 1)。这就是为什么结果是False

这种情况,例子4,浮点数的hash值和数字本身是不一样的,因为hash值应该是整数。并且这些数字并没有像它们在内存中那样表示。 (2.01 不作为 2.01 本身存储在内存中)。因此,它们的哈希值不同是可以接受的。

要回答示例1,让我们看一些代码。根据tuple hashing implementation,让我们使用 Python 程序计算哈希值

x, hash_mult = int("0x345678", 16), 1000003
x, hash_mult = (x ^ 2) * hash_mult, hash_mult + 82522
x = (x ^ -2) * hash_mult
print(x + 97531)                                   # -3713082714466793269

x, hash_mult = int("0x345678", 16), 1000003
x, hash_mult = (x ^ -2) * hash_mult, hash_mult + 82522
x = (x ^ 2) * hash_mult
print(x + 97531)                                   # -3713082714466793269

print(hash((-2, 2)))                               # -3713082714466793269

注意:这不仅适用于-2, 2,也适用于所有整数,除了上面看到的情况和所有 8 的倍数。

【讨论】:

    猜你喜欢
    • 2012-11-15
    • 1970-01-01
    • 2021-06-07
    • 2019-08-15
    • 1970-01-01
    • 2017-04-22
    • 2021-04-10
    • 2014-02-25
    • 1970-01-01
    相关资源
    最近更新 更多