一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等

一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等

一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等

攝影:產品經理
下廚:產品經理
在之前的文章裏面,咱們已經講到過,不單單是 Python,不少編程語言裏面,浮點數都不必定是精確的。最常被用來做爲例子的是:0.1 + 0.2。在 Python 裏面,這個加法的結果以下圖所示:
一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等編程

由於這個緣由,咱們顯然不能直接用等號判斷兩個浮點數是否相等,以下圖所示:編程語言

一日一技:在 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

運行效果以下圖所示:
一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等

math.isclose默認的偏差值是,你也能夠增長一個參數人工指定:

>>> math.isclose(0.1 + 0.2, 0.3, rel_tol=1e-5)

這裏設定偏差值爲。

一日一技:在 Python 裏面,如何正確判斷兩個浮點數相等

相關文章
相關標籤/搜索