元组上的哈希输出不一致
Inconsistent hash output on tuples
比较一些双元素元组的 hashes
for i in range(11):
print(i, hash((i,i)) == hash((-i,-i)))
我希望在 i==0
时获得 True
,其余时间获得 False
。看到这个我很惊讶:
0 True
1 False
2 True
3 True
4 True
5 True
6 True
7 True
8 False
9 True
10 True
为什么会这样?
据我所知,这与 问题中的问题不同,因为它与顺序无关,而与值本身有关。
散列值永远无法保证不会发生冲突,即使优秀的散列算法努力做到这一点。 Python 3.8 改进了散列算法,特别是对于元组,因此与 Python 3.7 相比,问题中的问题现在更难在 Python 3.8 中重现。
摘自changelog for Python 3.8.0 alpha 1:
bpo-34751: The hash function for tuples is now based on xxHash which
gives better collision results on (formerly) pathological cases.
Additionally, on 64-bit systems it improves tuple hashes in general.
Patch by Jeroen Demeyer with substantial contributions by Tim Peters.
为了将来参考,我最终使用此代码进行一致的元组散列:
import hashlib
import pickle
def hash2(data):
bytez = pickle.dumps(data)
hashed = hashlib.md5(bytez)
return int(hashed.hexdigest(), 16)
比较一些双元素元组的 hashes
for i in range(11):
print(i, hash((i,i)) == hash((-i,-i)))
我希望在 i==0
时获得 True
,其余时间获得 False
。看到这个我很惊讶:
0 True
1 False
2 True
3 True
4 True
5 True
6 True
7 True
8 False
9 True
10 True
为什么会这样?
据我所知,这与
散列值永远无法保证不会发生冲突,即使优秀的散列算法努力做到这一点。 Python 3.8 改进了散列算法,特别是对于元组,因此与 Python 3.7 相比,问题中的问题现在更难在 Python 3.8 中重现。
摘自changelog for Python 3.8.0 alpha 1:
bpo-34751: The hash function for tuples is now based on xxHash which gives better collision results on (formerly) pathological cases. Additionally, on 64-bit systems it improves tuple hashes in general. Patch by Jeroen Demeyer with substantial contributions by Tim Peters.
为了将来参考,我最终使用此代码进行一致的元组散列:
import hashlib
import pickle
def hash2(data):
bytez = pickle.dumps(data)
hashed = hashlib.md5(bytez)
return int(hashed.hexdigest(), 16)