<返回更多

Python | 无穷的哈希值是多少?

2023-02-03  今日头条  VT聊球
加入收藏

前言

Python/ target=_blank class=infotextkey>Python中,有一个内置函数 hash(),它可以生成任何对象的哈希值,在进行对象不比较的时候,其实就是比较对象的哈希值

但是,你是否做过下面的操纵?

>>> iNFTy = float('inf')
>>> infty
inf
>>> type(infty)
<class 'float'>
>>> hash(infty)
314159

这里创建了一个表示无穷的浮点数对象infty,然后将它作为hash()函数的参数,即得到无穷的哈希值,结果是31459,对这个结果的数字组成,应该并不陌生吧。

>>> import math
>>> int(math.pi*1e5)
314159

它就是组成 的部分数字。为什么会是这个结果,这里有什么玄妙吗?

没有什么玄妙的,都是语言中的规定。不要忘记,Python语言是一种高级编程语言,编程语言都是人工语言,所以就会有很多人为的硬性规定。

回到hash()函数,它是Python的一个内置函数,在上面的程序中调用它的时候,函数的指针由内置float类型(PyTypeObject PyFloat_Type)的tp_hash属性给出,即float_hash函数,并且以return _Py_HashDouble(v-> ob_fval)定义返回值,实现返回值的代码:

if (Py_IS_INFINITY(v))
    return v > 0 ? _PyHASH_INF : -_PyHASH_INF;

这里的_PyHASH_INF就定义为314159:

#define _PyHASH_INF 314159

所以,可以把hash(float('inf'))理解为系统的规定,或者,在Python3中,也可以说是sys.hash_info.inf的结果:

>>> import sys
>>> sys.hash_info
sys.hash_info(width=64, modulus=2305843009213693951, inf=314159, nan=0, imag=1000003, algorithm='siphash24', hash_bits=64, seed_bits=128, cutoff=0)
>>> sys.hash_info.inf
314159

这个结果,是有其历史原因的。在2000年8月,Tim Peters提交了一个代码,其中修复了当时Python的一个bug。内容如下(
https://Github.com/python/cpython/commit/39dce29365d287dc6b353b2a527dc11fe58dcfa6):

 

在这次提交的代码中,Tim Peters 将 static long float_hash(PyFloatObject *v 从Objects/floatobject.c中剥离出来,并且实现下面的返回值:return _Py_HashDouble(v->ob_fval);。在Obbjects/obbject.c中的long _Py_HashDouble(double v)里面增加了下面的两行:

if (Py_IS_INFINITY(intpart))
    /* can't convert to long int -- arbitrary */
    v = v < 0 ? -271828.0 : 314159.0;

由此可见,那个结果就是人为的规定。注意,上面代码中还有另外一个数字,271828,就是 自然常数 所包含的几个数字。

但是,如果在Python3中,负无穷的哈希值会是:

>>> hash(float('-inf'))
-314159

在Pyhton2中,结果就不同了:

>>> hash(float('-inf'))
-271828

后来还有一些细微的变化,可以参阅:
https://github.com/python/cpython/commit/985ecdcfc29adfc36ce2339acf03f819ad414869

声明:本站部分内容来自互联网,如有版权侵犯或其他问题请与我们联系,我们将立即删除或处理。
▍相关推荐
更多资讯 >>>