天天看點

四舍五入就用round( )?Python四舍五入的正确打開方式!

round( )函數簡介

菜鳥教程中介紹到,round() 函數作用就是,傳回浮點數x的四舍五入值。

> round( x [, n]  )
           

參數x,n均為數值表達式,傳回值為x的四舍五入值。n為保留的小數位數,不加n則隻保留x四舍五入後的整數部分。

>>> round(2.3)
2
>>> round(2.45, 1)
2.5
           

特殊情況

上面的結果并沒有錯誤,這裡再用2.675測試一下:

>>> round(2.675, 2)
2.67
           

顯然結果不符合四舍五入的規則。為什麼會這樣呢?原因是:round()函數隻有一個參數,不指定位數的時候,傳回一個整數,而且是最靠近的整數,類似于四舍五入,當指定取舍的小數點位數的時候,一般情況也是使用四舍五入的規則,但是碰到.5的情況時,如果要取舍的位數前的小數是奇數,則直接舍棄,如果是偶數則向上取舍。

這也就解釋了上述現象。可這樣一來用round()函數取浮點數的四舍五入值不就變得不可靠了嘛?這樣的函數設計的意義何在?網上搜了一圈答案,覺得這個說法比較準确:

python3(注意python2 和 3的round()是不一樣的,這裡僅以python3作說明)中round()對浮點數的取舍遵循的是“四舍六入五平分”,“五平分”就是根據取舍的位數前的小數奇偶性來判斷,奇偶平分,符合公平性原則(四舍五入不是公平的),這樣一來也就保證了在資料量較大的情況下,篩選資料的真實性。(數學渣,不知道這樣了解對否……)

為什麼需要平分呢?原因就是部分小數無法用二進制完整表示,如1.15,轉為二進制将是很長的一串數字:1.0010011001100110011001100110011001100110011001100110011 這可不是簡單的幾個位元組就能存放下的。是以這裡就出現了取舍的問題。

那麼正确的四舍五入是否無法實作了呢?當然是有解決辦法的。比如,當你需要四舍五入保留兩位小數的時候,可以将數值乘以100再除以100.0:

>>> round(2.675 * 100)/100.0
2.68
           

這樣可以解決部分浮點數四舍五入的問題。為什麼是部分呢?筆者發現:

>>> round(2.135*100)/100.0
2.13
           
四舍五入就用round( )?Python四舍五入的正确打開方式!

檢驗下過程:

>>> 2.135*100
213.49999999999997
           

WTF!是精度問題嘛!

>>> Decimal(2.135)*100
Decimal('213.4999999999999786837179272')
           
四舍五入就用round( )?Python四舍五入的正确打開方式!

無法了解是不是!!二進制的世界正常人真的不懂,盼望一下未來有可以直接計算十進制的硬體誕生吧。

總結

在用round()函數進行四舍五入時,如果你對結果有十足把握,并且這就是你想要的結果,那就放心大膽地使用。不然就老老實實寫個函數來實作吧,這不是什麼難事。