สรุป: มันไม่ใช่เรื่องบังเอิญ _PyHASH_INF
เป็น hardcoded เป็น 314,159ในการเริ่มต้นการดำเนินการ CPython ของงูใหญ่และได้รับเลือกเป็นค่าโดยพลการ (ชัดจากตัวเลขของπ) ที่โดยทิมปีเตอร์สในปี 2000
ค่าของการ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
เป็นฟังก์ชั่นในตัว เรียกมันบนวัตถุที่ลอย Python จะเรียกใช้ฟังก์ชั่นที่มีตัวชี้จะได้รับจาก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;
ที่_PyHASH_INF
ถูกกำหนดให้เป็น 314159:
#define _PyHASH_INF 314159
ในแง่ของประวัติศาสตร์การกล่าวถึงครั้งแรก314159
ในบริบทนี้ในรหัสไพ ธ อน (คุณสามารถค้นหาสิ่งนี้ด้วยgit bisect
หรือgit log -S 314159 -p
) ถูกเพิ่มโดยTim Petersในเดือนสิงหาคม 2000 ในสิ่งที่กระทำ39dce293ในตอนนี้cpython
เก็บ git
ข้อความยืนยันว่า:
แก้ไขสำหรับhttp://sourceforge.net/bugs/?func=detailbug&bug_id=111866&group_id=5470 นี่เป็นข้อผิดพลาดที่ทำให้เข้าใจผิด - "ข้อผิดพลาด" ที่แท้จริงคือการhash(x)
ให้ข้อผิดพลาดที่ส่งคืนเมื่อx
ไม่มีที่สิ้นสุด แก้ไขที่ ที่เพิ่มเข้ามาใหม่แมโครPy_IS_INFINITY
pyport.h
จัดเรียงโค้ดใหม่เพื่อลดความซ้ำซ้อนที่เพิ่มขึ้นในการแปลงข้อมูลจำนวนลอยและจำนวนเชิงซ้อนผลักดันแทงก่อนหน้าของเทรนต์ไปสู่ข้อสรุปเชิงตรรกะ แก้ไขข้อผิดพลาดที่หายากมากซึ่งการลอยตัวของลอยสามารถคืนค่า -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อี
เกี่ยวข้องในภายหลังกระทำ:
hash(float('nan'))
0