2012-03-01 14 views
1

配列Aの合計から配列Bの値のインデックスを見つける必要があるnumpyプログラムがあります。そして、悲しいことに、numpy配列のprecissionの問題は私にそれに問題:(Numpy配列の精度、別の配列の検索で克服する方法

A =配列([0.1,0.1,0.1,0.1,0.1])
B =配列([0.1,0.2,0.3,0.4,0.5])

B == 0.3
array([False、False、True、False、False]、dtype = bool)

B ==和([3])
アレイ([、FALSE FALSE、偽、偽、偽]、DTYPE = BOOL)

B ==和([2])
アレイ([、FALSE TRUE、FALSE、偽、偽]、DTYPE = BOOL)

和([2])
0.20000000000000001

和([2])

0.30000000000000004

配列Aの正確な合計である配列Bの値を確実に見つけることができますか?

敬具 テルモ

+1

を何が価値があるため、これは浮動小数点演算との生活の一般的な事実です。これは、numpy配列の場合と比べて、Pythonリストには違いはありません。基本的には、 '=='を使って浮動小数点の等価性をテストしないでください。 –

+1

Bの値の合計でBのバイナリ検索を行い、Bの値の差の絶対値をAの合計と比較します。Bの2つの値をチェックする必要があります。 Bで少し上または下にある可能性があります。 –

+0

FYI:https://github.com/numpy/numpy/commit/b9f0f1f8b54d0e4cf74ea5e7d80893d66585c4a1 '1.7'に' numpy.isclose() '関数があります。 –

答えて

1

あなただけの浮動小数点演算の効果を見ています。 (numpy配列の代わりにPythonリストを使用した場合も同じことが成り立ちます)

numpyで浮動小数点の「近い」比較を行う組み込み関数が実際には驚いています... 2つのnumpy配列を比較するのにnumpy.allcloseがありますが、ブール値配列ではなくTrueまたはFalseが返されます。

これを実行するのは、実際には少し難しいことです。 infは偽陽性と偽陰性でスローされます。さらに、警告を上げるので、我々は、一般的にそれを行う避けたいだろうそれらでinfまたはnanで二つの配列を差し引く...

import numpy as np 

def close(a, b, rtol=1.e-5, atol=1.e-8, check_invalid=True): 
    """Similar to numpy.allclose, but returns a boolean array. 
    See numpy.allclose for an explanation of *rtol* and *atol*.""" 
    def within_tol(x, y, atol, rtol): 
     return np.less_equal(np.abs(x-y), atol + rtol * np.abs(y)) 
    x = np.array(a, copy=False) 
    y = np.array(b, copy=False) 
    if not check_invalid: 
     return within_tol(x, y, atol, rtol) 
    xfin = np.isfinite(x) 
    yfin = np.isfinite(y) 
    if np.all(xfin) and np.all(yfin): 
     return within_tol(x, y, atol, rtol) 
    else: 
     # Avoid subtraction with infinite/nan values... 
     cond = np.zeros(np.broadcast(x, y).shape, dtype=np.bool) 
     mask = xfin & yfin 
     cond[mask] = within_tol(x[mask], y[mask], atol, rtol) 
     # Inf and -Inf equality... 
     cond[~mask] = (x[~mask] == y[~mask]) 
     # NaN equality... 
     cond[np.isnan(x) & np.isnan(y)] = True 
     return cond 

# A few quick tests... 
assert np.any(close(0.300001, np.array([0.1, 0.2, 0.3, 0.4]))) 

x = np.array([0.1, np.nan, np.inf, -np.inf]) 
y = np.array([0.1000001, np.nan, np.inf, -np.inf]) 
assert np.all(close(x, y)) 

x = np.array([0.1, 0.2, np.inf]) 
y = np.array([0.101, np.nan, 0.2]) 
assert not np.all(close(x, y)) 
関連する問題