2012-03-01 3 views
1

J'ai un programme numpy où j'ai besoin de trouver l'indice d'une valeur dans le tableau B à partir d'une somme du tableau A - et malheureusement les problèmes de précision des tableaux numpy me donne un problème avec cette :(Précision du tableau Numpy, comment surmonter avec rechercher un autre tableau

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

B == 0.3
tableau ([Faux, Faux, Vrai, Faux, Faux], dtype = bool)

B == somme (A [3])
réseau ([Faux, Faux, Faux, Faux, Faux], DTYPE = bool)

B == somme (A [2])
réseau ([faux, vrai, faux, faux, faux], DTYPE = bool)

somme

(A [2])
0,20000000000000001

somme (A [2])
0,30000000000000004

Comment puis-je être sûr de trouver la valeur dans le tableau B qui est la somme précise du tableau A ??

Meilleures salutations Termo

+1

Pour ce que ça vaut, cela est un fait de vie en général avec arithmétique en virgule flottante. Ce n'est pas différent pour les listes python que pour les tableaux numpy. Fondamentalement, ne teste pas l'égalité à virgule flottante en utilisant '=='. –

+1

Faites une recherche binaire dans B avec la somme des valeurs de B et comparez ensuite la valeur absolue de la différence de la valeur trouvée dans le B avec la somme de A. Vous aurez besoin de deux vérifier deux valeurs dans B parce que la somme pourrait être légèrement supérieur ou inférieur à la valeur désirée en B. –

+0

FYI: https://github.com/numpy/numpy/commit/b9f0f1f8b54d0e4cf74ea5e7d80893d66585c4a1 Il y aura une fonction 'numpy.isclose()' dans '1.7'. –

Répondre

1

Vous êtes juste de voir les effets de l'arithmétique en virgule flottante. (La même chose est vraie si vous avez utilisé une liste python au lieu d'un tableau numpy.)

Je suis plutôt surpris qu'il n'y ait pas de fonction intégrée pour faire des comparaisons de "virgule flottante" en numpy ... Il y a numpy.allclose qui le fait pour comparer entre deux tableaux numpy, mais il renvoie simplement True ou False plutôt qu'un tableau booléen.

Faire ceci en général est un peu compliqué. inf sera jeté dans les faux positifs et les faux négatifs. En outre soustraction de deux tableaux avec inf ou nan en eux soulèvera un avertissement, si nous voulons généralement éviter de faire cela ...

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)) 
Questions connexes