Numpy数组精度,如何克服与搜索另一个数组有关的问题

Numpy数组精度,如何克服与搜索另一个数组有关的问题,numpy,sum,Numpy,Sum,我有一个numpy程序,我需要从数组a的和中找到数组B中某个值的索引,不幸的是,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 数组([False,False,True,False,False],dtype=bool) B==和(A[:3]) 数组([False,False,False,False,False],dtype=bool) B==和(A[:2]) 数组([Fals

我有一个numpy程序,我需要从数组a的和中找到数组B中某个值的索引,不幸的是,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
数组([False,False,True,False,False],dtype=bool)

B==和(A[:3])
数组([False,False,False,False,False],dtype=bool)

B==和(A[:2])
数组([False,True,False,False,False],dtype=bool)

总和(A[:2])
200000000001

总和(A[:2])
300000000000000004

如何确保在数组B中找到数组A的精确和的值

致意
Termo

您只是看到了浮点运算的效果。(如果使用python列表而不是numpy数组,情况也是如此。)

事实上,我很惊讶numpy中没有内置函数来进行浮点“关闭”比较…有
numpy.allclose
用于比较两个numpy数组,但它只返回
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))

您只是看到了浮点运算的效果(如果使用python列表而不是numpy数组,情况也是如此)

事实上,我很惊讶numpy中没有内置函数来进行浮点“关闭”比较…有
numpy.allclose
用于比较两个numpy数组,但它只返回
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))

值得一提的是,这是浮点运算的普遍事实。python列表与numpy数组没有什么不同。基本上,不要使用
=
测试浮点相等性。使用B中的值和在B中进行二进制搜索,然后比较在B与A的总和。您需要两次检查B中的两个值,因为总和可能略高于或低于B中的所需值。仅供参考:将有一个
numpy.isclose()
函数在
1.7
中。不管它值多少钱,这是浮点运算的普遍事实。python列表和numpy数组没有什么不同。基本上,不要使用
==
测试浮点相等性。用B中的值和在B中进行二进制搜索,然后比较B中的绝对值在B中找到的值与A中的和的差值。您需要两次检查B中的两个值,因为总和可能略高于或低于B中的所需值。仅供参考:在
1.7
中将有一个
numpy.isclose()
函数。我不知道它是何时引入的,但numpy1.17有一个
np.isclose()
函数返回一个布尔数组。上面的文档是。我不知道它是什么时候引入的,但是numpy1.17有一个
np.isclose()
函数返回一个布尔数组。上面的文档是。