Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why don't NumPy floats give ZeroDivisionError?

I noticed that in the code:

import numpy as np    

a = 0.0
print a / a

b = np.array( [0.0] )
print b[0] / b[0]  

the first print function throws a ZeroDivisionError, but the second one outputs nan. I'm aware that type(b[0]) is numpy.float64, while type(a) is float. I have two questions:

1) Why was it implemented this way?

2) Is there anyway to have it throw a ZeroDivisionError?

like image 976
Garrett Avatar asked Dec 18 '13 22:12

Garrett


3 Answers

I must say, I am more surprised that the regular Python floats do throw an error. As far as I can understand, returning NaN is the correct way, given the way floats are defined in IEEE 754.

http://grouper.ieee.org/groups/754/faq.html#exceptions

Why doesn't division by zero (or overflow, or underflow) stop the program or trigger an error? Why does a standard on numbers include "not-a-number" (NaN)?

The 754 model encourages robust programs. It is intended not only for numerical analysts but also for spreadsheet users, database systems, or even coffee pots. The propagation rules for NaNs and infinities allow inconsequential exceptions to vanish. Similarly, gradual underflow maintains error properties over a precision's range.

When exceptional situations need attention, they can be examined immediately via traps or at a convenient time via status flags. Traps can be used to stop a program, but unrecoverable situations are extremely rare. Simply stopping a program is not an option for embedded systems or network agents. More often, traps log diagnostic information or substitute valid results.

Flags offer both predictable control flow and speed. Their use requires the programmer be aware of exceptional conditions, but flag stickiness allows programmers to delay handling exceptional conditions until necessary.

An error is an appropriate response when dealing with numbers that do not have such capabilities, such as integral division.

like image 69
Amadan Avatar answered Oct 25 '22 11:10

Amadan


To answer the second part of your question, just use this numpy function.

So I had your problem and to cure it I simply put np.seterr(all='raise') right after my import numpy as np statement.

Thereafter my try/except block around the statement that was generating a zero error worked.

This approach works if you're dividing an array by an array (using numpy's "broadcasting" or coordinatewise math scheme): it throws the error even if only one of the divisions is by zero.

like image 33
Mike O'Connor Avatar answered Oct 25 '22 09:10

Mike O'Connor


Amadan's answer is why it is this way. If you do want it to throw a ZeroDivisionError, you can use

if np.isnan(x):
    raise ZeroDivisionError

where x is the value you're checking. Like other numpy functions, though, np.isnan() takes a numpy array as an input and returns a boolean numpy array as output. So if you have myNumPyArray, you can use myNumPyArray[np.isnan(myNumPyArray] to show all of the NaN elements, or myNumPyArray[np.invert(np.isnan(myNumPyArray))] to show the non-NaN elements

like image 24
ackrause Avatar answered Oct 25 '22 10:10

ackrause