散列函数问题:hash(1)== hash(1.0)

时间:2009-08-04 16:17:40

标签: python hash dictionary

我有一个dict的实例,int s,float s,string s作为键,但问题是当aintbfloatfloat(a) == bd = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0} d[1] == '1.0' d[1.0] == '1.0' d['1'] == 1 d['1.0'] == 1.0 ,那么他们的哈希值是相同的,这就是我不想得到的,因为我需要唯一的哈希值案例以获得相应的价值。

示例:

d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0}
d[1] == '1'
d[1.0] == '1.0'
d['1'] == 1
d['1.0'] == 1.0

我需要的是:

{{1}}

4 个答案:

答案 0 :(得分:7)

1 == 1.0开始,如果是hash(1) != hash(1.0)的情况,它会极大地打破散列的语义(因此会断言和设置)。更一般地说,对于所有x == yhash(x) == hash(y)x暗示y必须始终如此(当然没有条件要求反向含义保持)。

所以你的dict d只有三个条目,因为你在dict显示中写的第二个条目会覆盖第一个条目。如果你需要强制相等只在相同的类型之间保持(而不是更普遍的数字),你需要一个包装器,如:

class W(object):

  def __init__(self, x):
    self.x = x
    self.t = type(x)

  def __eq__(self, other):
    t = type(other)
    if t != type(self):
      return False
    return self.x == other.x and self.t == other.t

  def __hash__(self):
    return hash(self.x) ^ hash(self.t)

  def __getattr__(self, name):
    return getattr(self.x, name)

根据您的确切需求,您可能还想覆盖其他方法(其他比较方法,例如__cmp____le__,算术方法,__repr__等等)。无论如何,这将允许您构建类似于您需要的词典,只需使用键W(1)而不是裸1W(1.0)而不是裸1.0(你可能不需要包装非数字,虽然如果你选择这样做没有任何伤害,如果所有的键都被包裹起来,它可以简化你的dict中的检索。)

答案 1 :(得分:6)

使用float作为字典键是“不明智的”,不可能保证两个浮点值将评估为相同的值。

最好的方法是将密钥乘以预定的小数位数,并使用该整数作为密钥。

编辑:很抱歉,你似乎不想要一个带有实数键的字典,你只想根据输入的类型格式化输出?

答案 2 :(得分:2)

如果你真的只是需要了解其中的差异,也许可以做一些像黑客这样的事情:

x = '1'
y = 1

hash(type(x) + x) != hash(type(y) + y)

答案 3 :(得分:1)

这并不能解决您的问题,而是来自Python 2.6's number documentation

  

实现者应该小心使相等的数字相等并将它们哈希到相同的值。

你可以通过制作浮动1.00001,或类似的东西吗?