處理浮點數

Python SELF TW
等級 5 , 課堂 4
開放

4.1 浮點數的四捨五入

浮點數(小數)用英文叫做 floating point number——有浮動小數點的數字:在美國,使用小數點將一個數字的整數部分與小數部分分開。因此得名float

正如我們已經討論過的那樣,當將浮點數(float)轉換為整數(int)時,它總是向下取整——即小數部分被捨棄。但很容易想像一種情況,即需要將小數四捨五入到最近整數。這種情況怎麼辦?

為此,Python 提供了一個內建函數round()。這個函數早於 math 庫的創建,因此不包括在內。向下取整和向上取整的函數在 math 庫中。

函數 round() 將數字四捨五入到最近的整數:


round(浮點數)

這個函數將返回一個整數,傳入的浮點數離這個整數最近。需要注意的是,如果小數部分等於 0.5,函數round() 使用的方法是四捨五入到最接近的偶數整數,這叫做 "銀行家的四捨五入" ,並且可以減少多次四捨五入的系統誤差。例如:

例子:

指令 結果
x = round(4.1) 4
x = round(4.5) 4
x = round(4.9) 5
x = round(5.5) 6
函數 math.ceil() 將數字向上取整為整數,例如:

指令 結果
x = math.ceil(4.1) 5
x = math.ceil(4.5) 5
x = math.ceil(4.9) 5

函數 math.floor() 將數字向下取整為整數,例如:

指令 結果
x = math.floor(4.1) 4
x = math.floor(4.5) 4
x = math.floor(4.9) 4

雖然向下取整更簡單的方法是使用類型轉換函數int()

指令 結果
x = int(4.9) 4

如果你覺得很難記住這些指令,可以來個小小的英文課:

  • math — 數學
  • round — 圓/四捨五入
  • ceiling — 天花板
  • floor — 地板

4.2 浮點數的結構

在 Python 中,float 類型可以存儲的數值範圍是 -1.7*10308 到 +1.7*10308。這麼大的範圍是由於float 類型的結構與整數類型完全不同。每個 float 類型的變量包含兩個數字:第一個叫做尾數,第二個叫做指數。

假設我們有一個數字 123456789,並將其存儲到一個float 類型的變量中。那麼這個數字將被轉換為1.23456789*108,在 float 類型內部將存儲兩個數字——234567898。紅色標記的是“數字的有效部分”(尾數),綠色的是指數。

這種方法允許存儲非常大的數字和非常小的數字。但是,由於數字的大小限制為 8 字節(64 位),並且部分位用於存儲指數(以及數字和指數的符號),尾數的最大長度被限制為 15 位數字。

這是一個非常簡化的描述浮點數的結構,更詳細的內容可以上網查找。

4.3 處理浮點數時的精度損失

在處理浮點數時,始終需要記住,浮點數是不精確的。總是會有四捨五入的錯誤、從十進制系統到二進制系統的轉換錯誤,最後是最常見的精度損失,尤其是在處理大小相差過大的數字的加減運算時。

最後這一點對於編程初學者來說,是最出人意料的情況。

比如從數字109 中減去1/109,我們將會得到109

相差過大的數字的減法 解釋

1000000000.000000000
-     0.000000001
1000000000.000000000
                            
第二個數字太小了,其有效部分被忽略(用灰色標出)。橙色標記的是15 個有效數字

怎麼說呢,編程可不是數學。

4.4 比較浮點數的危險性

比較浮點數時還有一個危險在等著程序員。因為在處理這些數字時,可能會累積一些四捨五入的錯誤,這可能導致本應相等的浮點數不相等,相反:本應不相等的數字卻相等。

例如:

指令 解釋
a = 1000000000.0 b = 0.000000001 c = a – b

在變量 a 中將是 1000000000.0

在變量 c 中將是 1000000000.0

(變量 b 中的數字太小了)

在上面的例子中,a 和 c 本不應相等,但它們卻相等。

或者另一個例子:

指令 解釋
a = 1.00000000000000001 b = 1.00000000000000002

在變量 a 中將是 1.0

在變量 b 中將是 1.0

在實踐中,浮點數的比較是這樣進行的:

取一個非常小的數。如果數字的差(取絕對值)小於這個小數,則它們被認為是相等的。例如:


a = 0.00000000012
b = 0.000000000011 

if abs(a - b) < 0.00001:
    print("相等")
else:
    print("不相等")
留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION