关于python:Numpy,除以零:同一操作的两个不同结果

Numpy, divide by zero: two different results for the same operation

在搜索了一点之后,我仍然在和numpy中零的除法作斗争。我对我马上报告的矛盾感到震惊:

1
2
3
4
5
6
from numpy import *

seterr(all='ignore')    # Trying to avoid ZeroDivisionError, but unsuccessful.

def f(x) :
    return 1./(x-1.)

有了这个,当我执行f(1.)时,我得到ZeroDivisionError: float division by zero

但是,当我定义z = array( [ 1., 1. ] )和执行f(z)没有错误,但是array([ inf, inf])

正如您所看到的,两个输出之间存在某种矛盾。我的第一个问题是为什么。

理想情况下,我希望把inf作为f(1.)的输出,或者至少是nan的输出,但不是一个错误(因此停止计算)。我的第二个问题是如何处理这个问题。注意我使用seterr失败的尝试。


1.是一个普通的python float,它们会引发异常,而不是使用nan/inf。当您调用f(1.)时,numpy不会以任何方式参与其中。仅仅执行from numpy import *(或者调用像seterr这样的numpy函数)并不能改变普通python类型的工作方式;它只会影响numpy对象的操作,并且只有显式创建numpy对象时,才会获得numpy对象。

当您显式地创建一个numpy对象时,例如在您的f(z)示例中,您将涉及numpy,它有自己的类型,不同于基本的python类型。值得注意的是,numpy数字类型确实使用了nan/inf。

据我所知,没有办法让普通的python float开始返回naninf,而不是引发异常,因此如果您希望同时支持标量和向量操作,那么必须使用numpy scalars而不是plain python float(如本问题所述)。


numpy与你的函数f无关。如果你想改变输出,你必须抓住ZeroDivisionError

1
2
3
4
5
6
7
import numpy

def f(x) :
    try:
        return 1./(x-1.)
    except ZeroDivisionError:
        return numpy.nan

或者使用Numpy的划分:

1
2
3
4
import numpy

def f(x) :
    return numpy.divide(1., (x-1.))

或者只将numpy类型传递给f

1
2
3
4
5
6
7
import numpy

def f(x) :
    return 1./(x-1.)

x = numpy.float_(1)
print f(x) # prints inf


它看起来像seterr用于numpy类型;它如何与python本机类型一起使用。另一方面,如果你这样做:

1
f(np.array((1,)))

您的seterr不应出现错误。