攝影:產品經理
下廚:產品經理
在之前的文章裏面,咱們已經講到過,不單單是 Python,不少編程語言裏面,浮點數都不必定是精確的。最常被用來做爲例子的是:0.1 + 0.2。在 Python 裏面,這個加法的結果以下圖所示:
編程
由於這個緣由,咱們顯然不能直接用等號判斷兩個浮點數是否相等,以下圖所示:編程語言
在工程上,咱們不要求絕對精確,只要求足夠精確就能夠了。因此,當咱們要判斷兩個數是否相等時,只須要判斷這兩個數的差值是否小於某一個特定的值便可。例如:ide
0.30000000000000004 0.3
它們的差值是0.00000000000000004,(十億億分之4),不管是測量重量仍是測量長度,這個差別均可以忽略不計,所以能夠認爲0.30000000000000004與0.3在偏差範圍內是相等的。3d
若是你們去網上搜索某些判斷浮點數是否相等的方法,你可能會發現下面這種寫法:code
def compare_float(a, b, precision): if abs(a - b) <= precision: return True return False
看起來彷佛沒有問題,例如我把 precision 設置爲,這不就是判斷a,b這兩個數字的差值的絕對值小於嗎?若是差值的絕對值小於這麼小的一個精度值,不就說明能夠判斷他們相等嗎?blog
可是等等,在代碼裏面,有一個<=,這個符號的意思是小於或者等於,有等於在裏面,因此if abs(a - b) <= precision等價於if abs(a - b) < precision or abs(a - b) == precision。ci
可是咱們一開始就說明了,兩個浮點數不能使用==來判斷是否相等,因此這裏abs(a - b) == precision獲得的結果原本就是不許確的,怎麼能夠用不許確的結果來講明另外一個不許確的結果?產品
因此,正確的作法,應該是把兩邊都擴大不少倍,讓他們都變成整數再來對比。it
例如我設置的精度爲,那麼咱們就把兩邊同時乘以10^9:io
if 1e9 * abs(a - b) <= 1: return True
因此比較浮點數是否相等的代碼應該改成:
def compare_float(a, b, precision): if precision == 0: return a == b elif precision < 0: raise Exception('precision 不能小於0') elif precision >= 1: if abs(a - b) <= precision: return True else: if (1 / precision) * abs(a - b) <= 1: return True return False
當精度設定爲0的時候,就是要求 a 和 b絕對相等,不能有偏差,此時能夠使用==來進行判斷。若是precision大於1,那麼此時能夠直接判斷。若是0 < precision < 1,那麼兩邊乘以,把浮點數對比轉換爲整數對比。
在 Python 3裏面,咱們有現成的庫math.isclose,它的用法以下:
>>> import math >>> math.isclose(0.1 + 0.2, 0.3) True
運行效果以下圖所示:
math.isclose默認的偏差值是,你也能夠增長一個參數人工指定:
>>> math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-5)
這裏設定偏差值爲。