x=1.0
i=1
while(1.0+x>1.0):
x=x/2
i=i+1
print i
后续问题,为什么 i=54 的值?
我的想法是循环不会结束,因为 (1.0+x) 的值将始终保持大于 1.0。但是在运行代码时,情况并非如此。
x=1.0
i=1
while(1.0+x>1.0):
x=x/2
i=i+1
print i
后续问题,为什么 i=54 的值?
我的想法是循环不会结束,因为 (1.0+x) 的值将始终保持大于 1.0。但是在运行代码时,情况并非如此。
为什么是 54?-- 实际上是 53,因为它是在你增加它之前
>>> 2.**-54
5.551115123125783e-17
>>> 2.**-53
1.1102230246251565e-16
>>> 2.**-52
2.220446049250313e-16
>>> sys.float_info.epsilon
2.220446049250313e-16
如果你把这么小的东西加到 1,它仍然是 1。
在处理浮点数或浮点数时,您会遇到臭名昭著的Floating Point Epsilon:
在您的情况下,这需要 54 次迭代才能低于该阈值(因为 Python 中的默认浮点类型是单精度,而单精度的浮点 epsilon 是:
def machineEpsilon(func=float):
machine_epsilon = func(1)
while func(1)+func(machine_epsilon) != func(1):
machine_epsilon_last = machine_epsilon
machine_epsilon = func(machine_epsilon) / func(2)
return machine_epsilon_last
因此:
In [2]: machineEpsilon(float)
Out[2]: 2.2204460492503131e-16
53 次迭代从何而来?
从代码中的这一行:
x=x/2
它将当前值分配x
给x/2
意味着在第 53 次迭代中,它变成了:
1.11022302463e-16
这小于浮点 epsilon。
正如已经指出的那样 - 这是因为float
s 的准确性。如果你想克服这个“限制”,你可以使用 Python 的fractions
模块,例如:
from fractions import Fraction as F
x = F(1, 1)
i=1
while(F(1, 1)+x>1.0):
print i, x
x = F(1, x.denominator * 2)
i=i+1
print i
(注意:这将一直持续到被打断)