Godoy
Godoy

Reputation: 87

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

After having searched around a little bit, I'm still struggling with divisions by zero in numpy. I am stunned by the contradiction I report right away:

from numpy import *

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

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

With this, when I execute f(1.), I get ZeroDivisionError: float division by zero.

However, when I define z = array( [ 1., 1. ] ) and execute f(z), I do not get any error, but array([ inf, inf]).

As you can see, there is kind of a contradiction between both outputs. My first question is why.

Ideally, I would like to get inf as the output of f(1.), or at least nan, but not an error (and therefore the stoppage of the calculation). My second question is how to manage this. Notice my failed attempt by making use of seterr.

Upvotes: 1

Views: 760

Answers (3)

Numpy is not involved in your function f. You'll have to catch the ZeroDivisionError if you want to alter the output.

import numpy

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

Or use numpy's division:

import numpy

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

Or only pass numpy types to f:

import numpy

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

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

Upvotes: 1

BrenBarn
BrenBarn

Reputation: 251378

1. is an ordinary Python float, and these raise exceptions instead of using nan/inf. When you call f(1.), numpy is not involved in any way. Just doing from numpy import * (or calling numpy functions like seterr) doesn't change anything about how ordinary Python types work; it will only affect operations on numpy objects, and you only get numpy objects if you explicitly create them.

When you do explicitly create a numpy object, as in your f(z) example, you involve numpy, which has its own types that differ from the basic Python types. Notably, numpy numeric types do use nan/inf.

As far as I know, there is no way to get plain Python floats to start returning nan or inf instead of raising exceptions, so you'll have to use numpy scalars instead of plain Python floats (as described in this question) if you want to support both scalar and vector operations.

Upvotes: 2

Thomas Baruchel
Thomas Baruchel

Reputation: 7517

It looks like seterr is intended to be used with Numpy types; how could it be used with Python native type. On the other hand, if you do:

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

No error should occur with your seterr.

Upvotes: 0

Related Questions