为什么Python的无穷大散列具有π的数字?

时间:2019-05-20 20:00:21

标签: python math hash floating-point pi

Python中无穷大的哈​​希具有与pi相匹配的数字:

>>> inf = float('inf')
>>> hash(inf)
314159
>>> int(math.pi*1e5)
314159

这仅仅是巧合还是故意的?

3 个答案:

答案 0 :(得分:201)

摘要:这不是巧合; _PyHASH_INF is hardcoded as 314159在Python的默认CPython实现中,并且被选为任意值(显然是从π的数字开始)by Tim Peters in 2000


hash(float('inf'))的值是数字类型的内置哈希函数的系统相关参数之一,而is also available在Python 3中则为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

(结果也with PyPy也一样。)


就代码而言,hash是一个内置函数。在Python浮点对象上调用它会调用函数,该函数的指针由内置浮点类型(PyTypeObject PyFloat_Type)的tp_hash attribute给定,其中isfloat_hash函数, definedreturn _Py_HashDouble(v->ob_fval),而has

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

其中_PyHASH_INFdefined as 314159:

#define _PyHASH_INF 314159

从历史的角度来看,Tim Peters添加了在此上下文中Python代码(您可以使用314159git bisect找到的git log -S 314159 -p的第一次提及)在2000年8月,现在在cpython git存储库中提交了39dce293

提交消息显示:

  

修复http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470。   这是一个误导性错误-真正的“错误”是hash(x)给出了一个错误   当x为无穷大时返回。固定的。向其中添加了新的Py_IS_INFINITY宏   pyport.h。重新排列代码以减少float和   复数,使Trent早些时候的努力达到了合理的结论。   修复了极其罕见的错误,即即使存在浮点数的哈希也可能返回-1   这不是一个错误(没有浪费时间来构造一个测试用例,这仅仅是   从代码中可以很明显地看出来)。改进了复杂的哈希,以便   hash(complex(x, y))不再系统地等于hash(complex(y, x))

尤其是,在此提交中,他摘录了static long float_hash(PyFloatObject *v)Objects/floatobject.c的代码,使其仅为return _Py_HashDouble(v->ob_fval);,以及{{1 }}他添加了以下几行:

long _Py_HashDouble(double v)

因此,如上所述,这是一个任意选择。请注意,271828由e的前十进制数字组成。

相关的以后提交:

答案 1 :(得分:32)

_PyHASH_INF等于314159的{​​{3}}。

我找不到关于此的任何讨论或提供原因的评论。我认为它或多或少是任意选择的。我想只要它们不将相同的有意义的值用于其他哈希,就没关系。

答案 2 :(得分:10)

确实

function findeventlog {
    # Get current month = eg. May
    # Find all files earlier than [get current month]

    # List all files that have last write time in the past.
    # Get-Date returns a DateTime that contains methods for addition
    $files = Get-Childitem -path c:\path\to\logs | ` # ` is used here for wrapping
      Where-Object { $_.LastWriteTime -le (get-date).AddMonths(-1) } 

    # define exclusion list of zip files = "*.zip"
    # Files collection can be filtered. ? is shorthand for where-object
    # For a list of all properties, refer to docs.microsoft.com or use Get-Member
    $files = $files | ? { $_.someProperty -ne something }

    # define event log folder = Drive\eventlogbackup\eventlogs 
    # define zip destination folder = F:\eventlogbackup\eventlog -filter -recurse

    # define zips to create = find items in event log folder and exclude (list)
    # define zips to create.count
    # zip (define zips to create)
    Compress-Archive -LiteralPath $files -Destination c:\my\archive\location
}

返回sys.hash_info.inf 。该值不会生成,而是内置在源代码中。 实际上,

314159

在python 2(it's -314159 now)中返回hash(float('-inf')) 或大约为-e。

使用所有时间中两个最著名的无理数作为哈希值的事实使得它不太可能是巧合。