x=1.0
i=1
while(1.0+x>1.0):
x=x/2
i=i+1
print i
後續問題,爲什麼是i = 54的值?爲什麼While循環終止?
我的想法是,循環不會結束,因爲(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的值?爲什麼While循環終止?
我的想法是,循環不會結束,因爲(1.0 + x)的值將始終保持大於1.0。但是在運行代碼時,情況並非如此。
由於inaccuracy of floating point,總會出現x
的值太小而導致Python無法存儲其值的情況,實際上它會變成0
。這需要54次迭代(53, actually)去那個階段,這就是爲什麼i
是54
例如,
>>> 1e-1000
0.0
其實一到浮點數(雙精度)接近於零,它需要比53'2更多的步驟。** - 1074'對'2。** - 1075'。這裏的關鍵是添加1 – JBernardo
爲什麼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默認浮點類型是單精度,併爲單精度浮點小量是:
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
(注:這將繼續下去,直到打斷)
因爲float精度 – JBernardo