2016-11-22 40 views
1

我想了解這個簡單例子背後的浮點算術。兩種碼在理論上在算術上是等價的,但顯然一系列的加法比單純的乘法增加了更多的誤差。浮點算術:總結與乘積錯誤

s=0.0 
for i in range(10): 
    s += 0.1 
print(s) 
print('%.30f' % s) 

0.9999999999999999 
0.999999999999999888977697537484 

但:

s=0.1 
s *= 10 
print(s) 
print('%.30f' % s) 
1.0 
1.000000000000000000000000000000 

我想明白是怎麼回事幕後。

據我瞭解,小數0.1的二進制表示從未準確,可以通過驗證:

print(0.1) 
print('%.30f' % 0.1) 
0.1 
0.100000000000000005551115123126 

所以在求和的順序,將餘下部分5.55e-18保持加起來變量,很快速增長。

但是,當乘法時,我認爲同樣的餘數也會增加,它會增加,但是這不會發生。這是爲什麼?轉換爲二進制之前的任何優化?

回答

2

它只是與如何對結果進行四捨五入(內部二進制)。 0.1 converts to

0.1000000000000000055511151231257827021181583404541015625

0.0001100110011001100110011001100110011001100110011001101in binary

Multiply that 10(1010二進制),你會得到

1.000000000000000000000000000000000000000000000000000001 

也就是說55顯著位;四捨五入爲53位,它等於1.0。

添加0.1十次,你會經歷一系列的舍入(你假設錯誤「總是加在變量上並且很快增長」是錯誤的 - 爲什麼將0.1加10次減少爲那麼??)。如果您在每次迭代後打印完整的十進制值,你應該看到

0.1000000000000000055511151231257827021181583404541015625 
0.200000000000000011102230246251565404236316680908203125 
0.3000000000000000444089209850062616169452667236328125 
0.40000000000000002220446049250313080847263336181640625 
0.5 
0.59999999999999997779553950749686919152736663818359375 
0.6999999999999999555910790149937383830547332763671875 
0.79999999999999993338661852249060757458209991455078125 
0.899999999999999911182158029987476766109466552734375 
0.99999999999999988897769753748434595763683319091796875 

看0.5和0.6之間發生了什麼,例如。添加內部二進制值0.5和0.1

0.1 + 0.0001100110011001100110011001100110011001100110011001101

答案是

0.1001100110011001100110011001100110011001100110011001101 

即55個比特;四捨五入至53位是

0.10011001100110011001100110011001100110011001100110011 

這在十進制是

0.59999999999999997779553950749686919152736663818359375

小於0.6,雖然你可能會認爲它是更大的。

+0

感謝您的詳細解釋。現在有道理。 – Raf

+0

可能值得補充的是,取整爲53位與IEEE-754浮點運算有關。 [https://docs.python.org/3/tutorial/floatingpoint.html#representation-error] – Raf