Turn off ZeroDivisionError?

N

Neal Becker

I'd like to turn off ZeroDivisionError. I'd like 0./0. to just give NaN,
and when output, just print 'NaN'. I notice fpconst has the required
constants. I don't want to significantly slow floating point math, so I
don't want to just trap the exception.

If I use C code to turn off the hardware signal, will that stop python from
detecting the exception, or is python checking for 0 denominator on it's
own (hope not, that would waste cycles).
 
R

Ryszard Szopa

I'd like to turn off ZeroDivisionError. I'd like 0./0. to just give NaN,
and when output, just print 'NaN'. I notice fpconst has the required
constants. I don't want to significantly slow floating point math, so I
don't want to just trap the exception.

What you are trying to do looks like something very, very wrong, in
the vast majority of cases. Think: normal Python code and the
interpreter itself are written under the assumption that dividing by
zero doesn't pass silently. Changing it is asking for bogus behavior.

Have you actually timed how big is the overhead of catching the
exception?

In [83]: import timeit

In [84]: x = """\
try:
1.0/rand.next()
except:
pass"""

In [85]: t = timeit.Timer(x, 'import random \nrand =
iter([random.randint(0,10) for i in xrange(1000000)])')

In [86]: x_nozero = "1.0/rand.next()"

In [87]: t_nozero = timeit.Timer(x_nozero, 'import random \nrand =
iter([random.randint(1,10) for i in xrange(1000000)])')

In [88]: t.repeat()
Out[88]: [0.91399192810058594, 0.8678128719329834,
0.86738419532775879]

In [89]: t_nozero.repeat()
Out[89]: [0.64040493965148926, 0.58412599563598633,
0.59886980056762695]

As you can see, the overhead isn't so huge.

If this overhead is too big for you, you should consider using a
different language (C? Fortran?) or at least a numeric package for
Python (NumPy?).

Anyway, turning off division by zero signaling looks like the wrong
answer to the wrong question.

HTH,

-- Richard
 
E

endangeredmassa

Would a wrapper function be out of the question here?

def MyDivision(num, denom):
if denom==0:
return "NaN"
else
return num / denom
 
M

Mark Dickinson

If I use C code to turn off the hardware signal, will that stop python from
detecting the exception, or is python checking for 0 denominator on it's
own (hope not, that would waste cycles).

Yes, Python does do an explicit check for a zero denominator. Here's
an excerpt from floatdiv.c in Objects/floatobject.c:

if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float division");
return NULL;
}

This is probably the only sane way to deal with differences in
platform behaviour when doing float divisions.
 
D

Dikkie Dik

Mark said:
Yes, Python does do an explicit check for a zero denominator. Here's
an excerpt from floatdiv.c in Objects/floatobject.c:

if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float division");
return NULL;
}

This is probably the only sane way to deal with differences in
platform behaviour when doing float divisions.
Are you sure?

It could very well be that 1/(smallest possible number)>(greatest
possible number). So I would also trap any errors besides trapping for
the obvious zero division.
 
B

bearophileHUGS

Mark Dickinson:
This is probably the only sane way to deal with differences in
platform behaviour when doing float divisions.

What Python run on a CPU that doesn't handle the nan correctly?

Bye,
bearophile
 
G

Grant Edwards

Yes, Python does do an explicit check for a zero denominator. Here's
an excerpt from floatdiv.c in Objects/floatobject.c:

if (b == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float division");
return NULL;
}

This is probably the only sane way to deal with differences in
platform behaviour when doing float divisions.

I've always found that check to be really annoying. Every time
anybody asks about floating point handling, the standard
response is that "Python just does whatever the underlying
platform does". Except it doesn't in cases like this. All my
platforms do exactly what I want for division by zero: they
generate a properly signed INF. Python chooses to override
that (IMO correct) platform behavior with something surprising.
Python doesn't generate exceptions for other floating point
"events" -- why the inconsistency with divide by zero?
 
S

Steve Holden

Dikkie said:
Are you sure?

It could very well be that 1/(smallest possible number)>(greatest
possible number). So I would also trap any errors besides trapping for
the obvious zero division.

What's so special about one? You surely don't expect the Python code to
check for all possible cases of overflow before allowing the hardware to
proceed with a division?

regards
Steve
 
N

Neal Becker

Would a wrapper function be out of the question here?

def MyDivision(num, denom):
if denom==0:
return "NaN"
else
return num / denom

I bought a processor that has hardware to implement this. Why do I want
software to waste time on it?
 
C

Christian Heimes

Grant said:
I've always found that check to be really annoying. Every time
anybody asks about floating point handling, the standard
response is that "Python just does whatever the underlying
platform does". Except it doesn't in cases like this. All my
platforms do exactly what I want for division by zero: they
generate a properly signed INF. Python chooses to override
that (IMO correct) platform behavior with something surprising.
Python doesn't generate exceptions for other floating point
"events" -- why the inconsistency with divide by zero?

I'm aware result is arguable and professional users may prefer +INF for
1/0. However Python does the least surprising thing. It raises an
exception because everybody has learned at school 1/0 is not allowed.
From the PoV of a mathematician Python does the right thing, too. 1/0 is
not defined, only the lim(1/x) for x -> 0 is +INF. From the PoV of a
numerics guy it's surprising.

Do you suggest that 1./0. results into +INF [1]? What should be the
result of 1/0?

Christian

[1]
http://en.wikipedia.org/wiki/Division_by_zero#Division_by_zero_in_computer_arithmetic
 
J

Jeff Schwab

Neal said:
I bought a processor that has hardware to implement this. Why do I want
software to waste time on it?

Will the amount of time wasted by the software exceed the amount of time
required to implement Python-level access to the hardware feature? At
any rate, the work-around should at least let you work on the rest of
the application, while a more efficient implementation can be developed.
 
J

Jeff Schwab

Neal said:
I bought a processor that has hardware to implement this. Why do I want
software to waste time on it?

Will the amount of time wasted by the software exceed the amount of time
required to implement Python-level access to the hardware feature? At
any rate, the work-around should at least let you work on the rest of
the application, while a more efficient implementation can be developed.
 
G

Grant Edwards

I'm aware result is arguable and professional users may prefer
+INF for 1/0. However Python does the least surprising thing.

It appears that you and I are surprised by different things.
It raises an exception because everybody has learned at school
1/0 is not allowed.

You must have gone to a different school than I did. I learned
that for IEEE floating point operations a/0. is INF with the
same sign as a (except when a==0, then you get a NaN).
From the PoV of a mathematician Python does the right thing,
too. 1/0 is not defined, only the lim(1/x) for x -> 0 is +INF.
From the PoV of a numerics guy it's surprising.

Do you suggest that 1./0. results into +INF [1]?

That's certainly what I expected after being told that Python
doesn't do anything special with floating point operations and
leaves it all up to the underlying hardware. Quoting from the
page to linked to, it's also what the IEEE standard specifies:

The IEEE floating-point standard, supported by almost all
modern processors, specifies that every floating point
arithmetic operation, including division by zero, has a
well-defined result. In IEEE 754 arithmetic, a/0 is positive
infinity when a is positive, negative infinity when a is
negative, and NaN (not a number) when a = 0.

I was caught completely off guard when I discovered that Python
goes out of its way to violate that standard, and it resulted
in my program not working correctly.
What should be the result of 1/0?

I don't really care. An exception is OK with me, but I don't
write code that does integer divide by zero operations.
 
M

Mark Dickinson

What Python run on a CPU that doesn't handle the nan correctly?

How about platforms that don't even have nans? I don't think either
IBM's hexadecimal floating-point format, or the VAX floating-point
formats
support NaNs. Python doesn't assume IEEE 754 hardware; though much
of its code
could be a lot simpler if it did :).
rywhere ;-).

Mark
 
G

Grant Edwards

I bought a processor that has hardware to implement this. Why do I want
software to waste time on it?

Exactly. Espeically when Python supposedly leaves floating
point ops up to the platform.
 
G

Grant Edwards

Will the amount of time wasted by the software exceed the amount of time
required to implement Python-level access to the hardware feature?

The "time required to implement Python-level access to the
hardware features" is simply the time required to delete the
lines of code that raise an exception when demon is 0.0
At any rate, the work-around should at least let you work on
the rest of the application, while a more efficient
implementation can be developed.

A more efficient implementation? Just delete the code that
raises the exception and the HW will do the right thing.
 
M

Mark Dickinson

platform does".  Except it doesn't in cases like this. All my
platforms do exactly what I want for division by zero: they
generate a properly signed INF.  Python chooses to override
that (IMO correct) platform behavior with something surprising.
Python doesn't generate exceptions for other floating point
"events" -- why the inconsistency with divide by zero?

But not everyone wants 1./0. to produce an infinity; some people
would prefer an exception.

Python does try to generate exceptions for floating-point events
at least some of the time---e.g. generating ValueErrors for
sqrt(-1.) and log(-1.) and OverflowError for exp(large_number).

I agree that the current situation is not ideal. I think the ideal
would be to have a floating-point environment much like Decimal's,
where the user has control over whether floating-point exceptions
are trapped (producing Python exceptions) or not (producing
infinities
and nans). The main difficulty is in writing reliable ANSI C that
can do this across platforms. It's probably not impossible, but
it is a lot of work.
 
C

Christian Heimes

Grant said:
You must have gone to a different school than I did. I learned
that for IEEE floating point operations a/0. is INF with the
same sign as a (except when a==0, then you get a NaN).

I'm not talking about CS and IEEE floating point ops. I was referring to
plain good old math. Python targets both newbies and professionals.
That's the reason for two math modules (math and cmath).
That's certainly what I expected after being told that Python
doesn't do anything special with floating point operations and
leaves it all up to the underlying hardware. Quoting from the
page to linked to, it's also what the IEEE standard specifies:

The IEEE floating-point standard, supported by almost all
modern processors, specifies that every floating point
arithmetic operation, including division by zero, has a
well-defined result. In IEEE 754 arithmetic, a/0 is positive
infinity when a is positive, negative infinity when a is
negative, and NaN (not a number) when a = 0.

I was caught completely off guard when I discovered that Python
goes out of its way to violate that standard, and it resulted
in my program not working correctly.

Python's a/0 outcome doesn't violate the standards because Python
doesn't promise to follow the IEEE 754 standard in the first place. Mark
and I are working hard to make math in Python more reliable across
platforms. So far we have fixed a lot of problems but we haven't
discussed the a/0 matter.

The best we could give you is an option that makes Python's floats more
IEEE 754 like:
.... r = a/0
.... print r
inf

Christian
 
P

Paul Rubin

Christian Heimes said:
Python targets both newbies and professionals.
That's the reason for two math modules (math and cmath).

Ehhh??? cmath is for complex-valued functions, nothing to do with
newbies vs. professionals.
 
J

Jeff Schwab

Grant said:
The "time required to implement Python-level access to the
hardware features" is simply the time required to delete the
lines of code that raise an exception when demon is 0.0

You mean the C code that implements the interpreter? Assuming the
developer is comfortable getting the Python source code, modifying it,
compiling and deploying the modified version: In the best case, the
change introduces a portability nightmare. In the worst case, you break
all kinds of existing code, possibly in the standard libraries, that
assumes an exception will be throw on any attempt to divide by zero.
A more efficient implementation? Just delete the code that
raises the exception and the HW will do the right thing.

"Just fork python" is not a simpler solution than "just use this
pure-python function." Whether it's worth the headache can be
considered at length, but in the meantime, the pure-python solution is
quicker, safer way to continue development of the client code that
requires the functionality (NaN on divide-by-zero).
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,819
Latest member
masterdaster

Latest Threads

Top