Python中的浮點數運算


第一次寫python,真是蛇年學python的節奏。

在本程序中想進行如下一個循環,並在最后一層中進行一個if判斷:當ini_allocation中得元素之和為1時進行下面的part。

 1  for i in range(0,11):
 2      ini_allocation[1] = 0.0
 3 
 4     for j in range(0,11):
 5          ini_allocation[2] = 0.0
 6 
 7          for k in range(0,11):
 8              ini_allocation[3] = 0.0
 9 
10              for ii in range(0,11):
11                  if ini_allocation[2]+ini_allocation[3]+ini_allocation[1]+ini_allocation[0] == 1.0:

#每個ini_allocation在循環末尾都會遞增0.1

在運行的過程中,發現ini_allocation無法遍歷到[0.0, 0.0, 0.2, 0.8]以上,也就是ini_allocation[3]遞增到0.8時,if語句的邏輯值已經為false。

為此,繼續采用以下代碼進行debug

1             for ii in range(0,11):
2                 if ini_allocation == [0.0, 0.0, 0.2, 0.8]:
3                     print "here"
4                 if ini_allocation[2]+ini_allocation[3]+ini_allocation[1]+ini_allocation[0] == 1.0:
5                     print "true"
6                 else:
7                     print "false"

在terminal中輸出結果,既沒有“here”,也沒有“true”。ini_allocation[3]根本不等於0.8啊,且ini_allocation之和不為1.0. 額,難道0.2+0.8不等於1.0么?

 

雖然python能很好地支持浮點數運算,但是python中浮點數是用二進制分數進行表示的。以上代碼中得浮點數是由十進制分數表示,因此在其轉換為二進制分數時面臨着尾數上的截斷誤差。為什么會有截斷誤差呢?首先要從十進制小數轉換為二進制小數的方法說起,

已知十進制小數B, 可以將B展開為2的負指數冪的級數,有

B=a*(2^-1)+b*(2^-2)+c*(2^-3)+...

那么將B轉換為二進制小數時,只需要進行以下的步驟,其中A代表的是二進制小數的小數部分,i從小數第一位開始計數:

B = B*2
i = 1
LOOP 
  IF B > 1
    A[i]=1
  ELSE
    A[i]=0
  i++
END

大部分小數B不能由2的負指數冪的有限級數表示,如0.7,其二進制小數位無線循環小數。但是計算機的位數有限,無法存儲無限位的小數,因此會在小數末尾位將不能存儲的部分進行截斷,產生截斷誤差。

最初的程序中,從0.0遞增到1.0,不免會遇到0.5,0.7這類二進制下無限循環小數,產生截斷誤差。而python只會呈現(display)出這些小數的近似值,因此我們的ini_allocation[3]可能和0.8不等,而且理論上誤差是隨意的。

如何解決這樣的問題呢?對於精度要求不高的程序,如本程序只要求精確到小數點第一位,那么我們調用decimal模塊提高浮點數運算的精度,然后將精確位以后的小數位給“人工截斷”

from decimal import *

利用round函數進行截斷操作,該函數第一個變量是需要截斷的浮點數,第二個是精確的位數。

1    sum2 = Decimal(ini_allocation[0])+Decimal(ini_allocation[1])+Decimal(ini_allocation[2])+Decimal(ini_allocation[3]) # float calculation
2    sum2 = round(sum2,1) # reduce the precision to 1 deci

通過這樣,就消除浮點數對本程序的影響了,這樣0.8+0.2=1.0了。

 

References:

http://docs.python.org/2/tutorial/floatingpoint.html   the float-number in python

http://docspy3zh.readthedocs.org/en/latest/tutorial/floatingpoint.html   the float-number in python

http://blog.csdn.net/unicode1985/article/details/1606067   decimal and round()

http://baike.baidu.com/view/1426817.htm   10-binary to 2-binary 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM