2013-08-19 66 views
2

谷歌搜索一段時間後,我在這裏發佈求助。不同的行爲float32/float64 numpy變量

我有兩個從函數返回的float64變量。 他們兩人顯然是1:當變量定義FLOAT32,在這種情況下,「Y < 1」語句不出現

>>> x, y = somefunc() 
>>> print x,y 
>>> if x < 1 : print "x < 1" 
>>> if y < 1 : print "y < 1" 
1.0 1.0 
y < 1 

行爲更改。

我嘗試設置

np.set_printoptions(precision=10) 

期待看到變量,但即使如此,在打印時兩者顯示爲1.0之間的差異。

我在這一點上有點困惑。 有沒有辦法可視化這些float64數字的區別? 可以「如果/然後」可靠地檢查float64數字嗎?

感謝 Trevarez

+3

我不明白你的問題。很顯然,錯誤出現在打印表示中,其中'y'小於'float64'情況下的一個,並且由於舍入錯誤而使用'float32'時等於(或大於)'1'。在處理浮點值時,你永遠不會使用相等的比較。修正一個最小誤差(例如'epsilon = 1e-16'或更小/更大取決於應用)並且如果abs(number-1)#number足夠接近於1,則認爲是1。 – Bakuriu

+0

@Bakuriu你可以發佈這個答案......你幾乎可以解釋發生了什麼 –

回答

4

打印值不正確。在使用float64時,y小於1,在使用float32時大於或等於1。這是預期的,因爲舍入誤差取決於float的大小。

爲了避免這種問題,在處理浮點數時,您應該總是決定一個「最小誤差」,通常稱爲epsilon,而不是比較相等性,檢查結果是否距目標最遠epsilon值:

In [13]: epsilon = 1e-11 

In [14]: number = np.float64(1) - 1e-16 

In [15]: target = 1 

In [16]: abs(number - target) < epsilon # instead of number == target 
Out[16]: True 

特別地,numpy已經提供np.allclose其可以是比較對於給定某個容差平等陣列有用的。即使參數不是數組(例如,np.allclose(1 - 1e-16, 1) -> True),它也可以工作。

但是,請注意,numpy.set_printoptions不會影響如何打印np.float32/64。它僅影響如何陣列印:

In [1]: import numpy as np 

In [2]: np.float(1) - 1e-16 
Out[2]: 0.9999999999999999 

In [3]: np.array([1 - 1e-16]) 
Out[3]: array([ 1.]) 

In [4]: np.set_printoptions(precision=16) 

In [5]: np.array([1 - 1e-16]) 
Out[5]: array([ 0.9999999999999999]) 

In [6]: np.float(1) - 1e-16 
Out[6]: 0.9999999999999999 

另外請注意,這樣做print y或交互式解釋評估y給出了不同的結果:

In [1]: import numpy as np 

In [2]: np.float(1) - 1e-16 
Out[2]: 0.9999999999999999 

In [3]: print(np.float64(1) - 1e-16) 
1.0 

不同的是,print電話str在評估呼叫repr

In [9]: str(np.float64(1) - 1e-16) 
Out[9]: '1.0' 

In [10]: repr(np.float64(1) - 1e-16) 
Out[10]: '0.99999999999999989' 
+0

謝謝Bakuriu, 這是一個相當全面的答案,澄清我的疑惑。 – Trevarez

+0

我只是想知道Numpy提供的函數「numpy.where」在浮動的這些細節上沒有警告,這有什麼意義? 從文檔中可以看出,它可以直接與浮標一起使用,而不必關心精度問題: >>> x = np.arange(9。)。reshape(3,3) >>> x [np。其中(x> 3.0)] array([4.,5.,6.,7.,8.]) – Trevarez

+0

@Trevarez它不是* numpy的問題。這是*任何*浮點計算的問題。這是你應該知道的東西(參見例如[每個計算機科學家應該知道的關於浮點運算的知識](http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html ))。如果你想檢查哪裏的值大於3.0,那麼你可以簡單地減去這個epsilon(即'x [np.where((x-epsilon)> 3.0)]')。 – Bakuriu

1
In [26]: x = numpy.float64("1.000000000000001") 

In [27]: print x, repr(x) 
1.0 1.0000000000000011 

換句話說,你用的精度損失在print聲明所困擾。該值與1略有不同。

+0

看到,'print'輸出11位有效數字,float64有15個左右。 –

+0

謝謝Qarma,這基本上就是你所指的。 – Trevarez

0

按照我在這裏提供的建議,我總結了這樣的答案:

爲了比較浮動,程序員必須定義一個最小距離(eps),他們被認爲是不同的(eps = 1e-12,for例)。這樣做,條件應該這樣寫:

Instead of (x>a), use (x-a)>eps 
Instead of (x<a), use (a-x)>eps 
Instead of (x==a), use abs(x-a)<eps 

它們之間固定爲1

希望它可以幫助別人,因爲它幫助我這並不適用於因爲差異整數之間的比較。