[python] 파이썬의 무한대 해시 숫자가 π 인 이유는 무엇입니까?

파이썬에서 무한의 해시는 pi와 일치하는 숫자를 갖습니다 .

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

우연의 일치 일까, 아니면 의도적 인 것일까?



답변

_PyHASH_INF되고 상수로 정의는 동일 314159.

이에 대한 토론이나 이유를 알려주는 의견을 찾을 수 없습니다. 나는 그것이 다소 임의로 선택되었다고 생각합니다. 다른 해시에 동일한 의미의 값을 사용하지 않는 한 중요하지 않다고 생각합니다.


답변

요약 : 우연의 일치가 아닙니다. 파이썬의 기본 CPython 구현에서 _PyHASH_INF314159하드 코딩 되었으며 2000 년 Tim Peters에 의해 임의의 값 (π의 숫자에서 분명히 선택됨)으로 선택 되었습니다 .


의 값은 hash(float('inf'))숫자 유형의 내장 해시 함수의 시스템에 의존하는 매개 변수 중 하나이며, 도 사용할 수 있습니다sys.hash_info.inf파이썬 3 :

>>> 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

( PyPy와 동일한 결과 도 있습니다.)


코드 측면 hash에서 내장 함수입니다. 그 포인터으로 제공되는 기능 파이썬 플로트 객체를 호출합니다 호출 tp_hash속성 내장 된 플로트 타입 (의 PyTypeObject PyFloat_Type) 이다float_hash 기능, 정의return _Py_HashDouble(v->ob_fval)차례로, 이는

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

여기서 314159 _PyHASH_INF정의됩니다 .

#define _PyHASH_INF 314159

역사의 측면에서의 첫 번째 언급 314159파이썬 코드에서이 맥락에서은 (당신이 이것을 찾을 수 있습니다 git bisect또는 git log -S 314159 -p추가되었다) 팀 피터스 (Tim Peters) 지금 커밋 무엇에, 2000 년 8 월 39dce293을cpython자식 저장소.

커밋 메시지는 다음과 같이 말합니다.

http://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 수정되었습니다 . 이것은 오해의 소지가있는 버그였습니다. 진정한 “버그”는 무한대 일 hash(x)때 오류를 반환했습니다 x. 고쳤다. 에 새 Py_IS_INFINITY매크로를 추가 했습니다
pyport.h. 부동 소수점과 복소수의 해싱에서 중복되는 중복을 줄이기 위해 코드를 재정렬하여 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);, 그리고 정의에 long _Py_HashDouble(double v)에서 Objects/object.c그가 선을 추가 :

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

언급했듯이 임의의 선택이었습니다. 271828은 e 의 처음 몇 십진수로 구성 됩니다.

관련 커밋 :


답변

과연,

sys.hash_info.inf

을 반환합니다 314159. 값은 생성되지 않으며 소스 코드에 내장되어 있습니다. 사실로,

hash(float('-inf'))

-271828파이썬 2에서, 또는 대략 -e를 반환합니다 ( 지금 -314159입니다). ).

가장 유명한 두 가지 비이성적 인 숫자가 해시 값으로 사용된다는 사실은 이것이 우연의 일치가 아닐 수 있습니다.


답변