这个问题源于浮点数在计算机中的存储方式。
简而言之:它们被存储为有限数量的有效数字、一个基数和一个指数。然后计算机知道将有效数字按以指数为底的基数来缩放以获得该值。数据量是特定于机器的:对于 32 位机器,23 位用于有效数字,8 用于指数,1 用于底数,64 位机器将有 53 位用于 sig figs, 8 为指数,1 为底数。
然后通过添加/减去有效数字和指数之间的差异来完成加法和减法。
您正在生成非常大的整数,hash(k)
并试图获取向下舍入int(y*T)
和浮点数之间的差异y*T
。当 Python 解释器尝试获取 afloat
和 an之间的差异int
时,它会将int
a 转换为浮点数,以y*T
存储一定数量的有效数字。当您尝试从两个高数量级数中获得低数量级差异时,就会出现问题,或者通常任何时候差异的数量级与所涉及的数字有很大差异。低位有效数字将在计算中丢失。
这是我为测试您的方法而编辑的版本。添加的参数c
是一个常数,我怀疑它有助于规范化您的结果。
import math
def h(k,M,c):
y = hash(k)
print "hash = ", y
T = (math.sqrt(5)-1)/(2*c)
print "y*T = ", y*T
print "int(y*T) = ", int(y*T)
print "(y*T) - int(y * T) = ",(y*T) - int(y * T)
print "M*((y*T) - int(y * T)) = ", M*((y*T) - int(y * T))
return(int(M*((y*T) - int(y * T))))
print(h('test',2,c))
随着 c 的增加,实际上这两个数字的差异出现在越来越接近的数量级上,您开始看到 的值(y*T) - int(y * T)
远离0
。示例输出如下:
>>>h('test',2,10)
hash = 2314058222102390712
y*T = 1.43016663321e+17
int(y*T) = 143016663320543088
(y*T) - int(y * T) = 0.0
M*((y*T) - int(y * T)) = 0.0
h(test,2,10) = 0
>>>h('test',2,1000)
hash = 2314058222102390712
y*T = 1.43016663321e+15
int(y*T) = 1430166633205430
(y*T) - int(y * T) = 0.75
M*((y*T) - int(y * T)) = 1.5
h(test,2,1000) = 1
>>>h('test',2,10000000)
hash = 2314058222102390712
y*T = 1.43016663321e+11
int(y*T) = 143016663320
(y*T) - int(y * T) = 0.543090820312
M*((y*T) - int(y * T)) = 1.08618164062
h(test,2,10000000) = 1
>>>h('test',2,10000000000000)
hash = 2314058222102390712
y*T = 143016.663321
int(y*T) = 143016
(y*T) - int(y * T) = 0.66332054307
M*((y*T) - int(y * T)) = 1.32664108614
h(test,2,10000000000000) = 1
作为我正在谈论的现象的一个附加示例:
y = hash('test')
print y
y = float(y)
print y
y = int(y)
print y
输出:
2314058222102390712
2.3140582221e+18
2314058222102390784
仅仅通过简单地切换到浮点数并返回到整数,最后两位数字不再可靠,因此可以看出低于此值的任何内容也会丢失。