On 11.10.2012 13:35, Steven D'Aprano wrote:
I would gladly give up a small amount of speed for better control over floats, such as whether 1/0.0 raised an exception or returned infinity.
If I wanted fast code, I'd be using C. I'm happy with *fast enough*.
For example, 1/0.0 in a continued fraction is generally harmless, provided it returns infinity. If it raises an exception, you have to write slow, ugly code to evaluate continued fractions robustly. I wouldn't expect 1/0.0 -> infinity to becomes the default, but I'd like a runtime switch to turn it on and off as needed.
For those who use Python for numerical or scientific computing or computer graphics this is a real issue. First: The standard way of dealing with 1/0.0 in this context, since the days of FORTRAN, is to return an inf. Consequently, that is what NumPy does, as does Matlab, R and most C programs and libraries. Now compare:
1.0/0.0
Traceback (most recent call last): File "<pyshell#0>", line 1, in <module> 1.0/0.0 ZeroDivisionError: float division by zero With this:
import numpy as np np.float64(1.0)/np.float64(0.0) inf
Thus, the NumPy float64 scalar behaves differently from the Python float scalar! In less than trivial expressions, we can have a combination of Python floats and ints and NumPy types (arrays or scalars). What this means is that the behavior is undefined. You might get an inf, or you might get an exception. Who can tell? The issue also affects integers:
1/0
Traceback (most recent call last): File "<pyshell#5>", line 1, in <module> 1/0 ZeroDivisionError: integer division or modulo by zero whereas:
np.int64(1)/np.int64(0) 0
np.int32(1)/np.int32(0) 0
And with arrays:
np.ones(10, dtype=np.int)/np.zeros(10, dtype=np.int) array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
np.ones(10, dtype=np.float64)/np.zeros(10, dtype=np.float64) array([ inf, inf, inf, inf, inf, inf, inf, inf, inf, inf])
I think for the sake of us who actually need computation -- believe it or not, Python is rapidly becoming the language of choice for numerical computing -- it would be very nice is this was controllable. Not just the behavior of floats, but also the behavior of ints. A global switch in the sys module would make life a lot easier. Even better would be a context manager that allows us to set up a "numerical" context for local expressions using a with statement. That would not have a lasting effect, but just affect the context. Preferably it should not even propagate across function calls. Something like this: def foobar(): 1/0.0 # raise an exception 1/0 # raise an exception with sys.numerical: 1/0.0 # return inf 1/0 # return 0 foobar() (NumPy actually prints divide by zero warnings on their first occurrence, but I removed it for clarity.) Sturla Molden