## Python division by zero is not IEEE compliant

October 10th, 2013 | Categories: Julia, matlab, programming, python | Tags:

From the wikipedia page on Division by Zero: “The IEEE 754 standard specifies that every floating point arithmetic operation, including division by zero, has a well-defined result”.

MATLAB supports this fully:

>> 1/0
ans =
Inf
>> 1/(-0)
ans =
-Inf
>> 0/0
ans =
NaN

Julia is almost there, but doesn’t handled the signed 0 correctly (This is using Version 0.2.0-prerelease+3768 on Windows)

julia> 1/0
Inf

julia> 1/(-0)
Inf

julia> 0/0
NaN

Python throws an exception. (Python 2.7.5 using IPython shell)

In [4]: 1.0/0.0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
in ()
----> 1 1.0/0.0

ZeroDivisionError: float division by zero

In [5]: 1.0/(-0.0)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
in ()
----> 1 1.0/(-0.0)

ZeroDivisionError: float division by zero

In [6]: 0.0/0.0
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
in ()
----> 1 0.0/0.0

ZeroDivisionError: float division by zero

Update:
Julia does do things correctly, provided I make it clear that I am working with floating point numbers:

julia> 1.0/0.0
Inf

julia> 1.0/(-0.0)
-Inf

julia> 0.0/0.0
NaN
1. Meanwhile, JavaScript behaves uncharacteristically sensibly:

> 1/0
Infinity
> -1/0
-Infinity
> 0/0
NaN

2. You are right. Pure Python is not able to do it. But you can use numpy, whose divison is IEEE compliant.

In [1]: import numpy as np

In [2]: np.divide(1.,0)
Out[2]: inf

In [3]: np.divide(1.,-0)
Out[3]: inf

In [4]: np.divide(0.,0)
Out[4]: nan

3. gosh, that’s a lot of typing!
np.divide(0.,0) vs 1.0/0.0

4. Mike: if you’re a hardcore numpy user, all your floating point numbers are stored in numpy arrays, and you can use the “/” operator on them directly.

import array from numpy
array(1.0) / array(-0.0)

Gives -Inf. If the arrays have variable names attached, the code is just “x / y”.

5. Python is a programming language with deterministic exact results and to throw an exception is expected result when operation is invalid, result is undefined.

1/0 is maybe inf when IEEE 754 but is not correct when you calculate accounting (account balance etc.)

and to be correct lim x->0 1/x = inf and not 1/0 = inf!

For different behaviour you can still use numpy

6. Sadly, sci computing w/ Python is almost always about typing a lot. A lot of imports, a lot of nested namespaces, a lot of functions…

7. It’s great that Numpy does things correctly but I really wish it ‘Just Worked’ in pure Python. If some people don’t want IEEE behaviour, as Norris suggests, I’d settle for a some sort of pragma or import or whatever that simply switched on full IEEE compliance.

8. What I’d actually like to see is a way to globally handle exceptions and have the code continue where it left off. So, for another example, one could globally change the behavior of list.index to return -1 if the entry wasn’t found.
But if we’re allowing some sort of pragma, I’d love to see complex numbers replaced by quaternions, with a pragma to specify whether ‘i’ or ‘j’ is used as the preferred square root of -1. This would solve the problem of python only support 1j and not 1i, while adding useful functionality, including 3D vectors. In the meantime, here a prototype: https://www.dropbox.com/s/e0ok1zqzcd6mktn/quaternion.py but AFAIK there’s no way to have it allow the obvious input format (e.g., 1+2i-3j+4k).

9. Python is not a language for scientific computing per se. It is well designed to be used in different contexts for people with completely different backgrounds. To an ordinary pragrammer division by zero must throw exception as other languages do. The case is even more subtle here because all types are implicit in python. Comparing python to matlab is not a right one either, matlab is designed for scientific computing, python was not. However the design was good enough to make it a very good choice for scietific computing using libraries like numpy, scipy.

You are correct that for heavy-duty computation, pure Python isn’t a good choice. But there’s no reason why it couldn’t be used for light-duty scientific computing, and it’s perfectly reasonable to ask that it handle floating point according to the IEEE standard (which allows control of division-by-zero behavior). When I was an “ordinary programmer”, I never expected division by zero to unconditionally throw an exception–I expected to be able to control that behavior. For the first few processors that I used (in assembly language), an attempt to divide by zero unconditionally resulted in a no-op.

11. Also, in matlab

> 1^Inf
NaN

but in python, julia, octave the result is 1

12. It’s annoying that python always-signals on floating point divide by zero, but it does not follow that Python is less IEEE 754-compliant than languages that never signal. (One wonders what SIGFPE is doing in the POSIX standard if that were true.)

Now, here’s someone complaining about the exact opposite problem in Java, that you can’t make it raise exceptions on floating point divide by zero:

So, this W. Kahan fellow says that Java, Matlab et al’s practice of never signaling floating point exceptions is not compliant, and you say that Python’s always-signaling is not compliant, how can you tell who’s right?

It might help to learn that Kahan was effectively the lead designer on IEEE 754 itself. So there you go.

(And the answer is that a compliant implementation would let you choose whether exceptions return NaNs or run traps.)

13. 1/.0 is deterministic and well-defined to yield an infinity, which in turn may throw an exception if enabled. If someone uses floating point for accounting then his fingers shall be chopped off and programming license revoked.

Python behavior is, on the other hand, inconsistent. Try evaluating 1./1e-323. Why it is not the same as 1/.0? It should be. Why on earth whether 1/x throws or not depends on the input noise of x?