Python 3 behavior: Divide by zero with no exceptions

Hi all.

So far, I have made a small changes of Python 3 behavior: it can divide by 0, but it returns a value, instead of a exception.

I re-programed floatobject.c and longobject.c. It only takes me few minutes to do this.

The idea is:

  • Return inf (known as positive infinity) when the numerator is larger than 0.
  • Return -inf (known as negative infinity) when the numerator is smaller than 0.

Some problems in dividing by zero:

  • 0/0 is undefined, since it’s because the conflict in calculating of limitation of equation when x approach 0. The exception is still returned
  • i/0 (where i is the imaginary number) is undefined. The exception is still returned
  • Dividing a integer, no matter whether it is negative or positive, the result always returns inf. No exception is thrown.

The image below descripts how the new Python 3 actually can do when dividing by zero.

1 Like

For Python, i/0 should be 1j/0. If 1/0 is float('inf') then 1j/0 should be complex('infj') (that’s complex(0, float('inf'))).

2 Likes

I don’t think it’s a good idea for this behaviour to change automatically with the Python version, but it seems nice to have the option.

Floating-point numbers have a concept of signed zero. The sign should be taken into account when this is used in the denominator. The meaning of 0.0 is really more like limx->0+ x, and similarly for “negative zero”.

This seems like what NaN is for.

Unlike with real numbers, the “complex zero” doesn’t easily convey the angle at which 0 is approached. (0.0, -0.0, 0.0j, -0.0j are only four possibilities out of, as mathematicians reckon, uncountably many.) Consequently, dividing by it doesn’t give a clear result. Even if the angle is known, to specify the result properly, you’d need (positive) “infinity” paired with an angle, not the usual real-part + imaginary-part representation. (You can get some really weird behaviour if you try to mess around creating these kinds of values.) There is also in complex analysis the concept of “complex infinity” (complex value of infinite magnitude and unspecified angle), or the “line / circle at infinity” (the set of all values of infinite magnitude).

I probably still got some pedantic details wrong. The point I am trying to make is that complex numbers are… complex, and it would be better not to try to extend their functionality if there’s a chance of giving incorrect results.

My first thought is that I would expect a signed result. In integers, 0 is normally considered positive rather than negative. Here, it’s hard to draw inspiration from mathematics, because integers are not closed under division.

2 Likes

This is a change that is not backwards compatible and as such I cannot see being put into python.

Are there any languages that have this semantic for divide by zero?

1 Like

Are there any languages that have this semantic for divide by zero?

JavaScript

I don’t care much about how the new Python 3 behaves.

I only care how many changes in my code. If the new Python 3 applies this, guess so many codes in the world will be changed.

1 Like

I will consider this situation.

In fact, our lab returns different results, and these are all about the complex, or go to the inf.
I am still figuring out which result is the best, and in what situation.

This is a bug in the Python division. I will also investigate the problem.

1 Like

Just a couple minutes ago, I have tested these conditions.

The returned results (including exceptions) are modified.

1 Like

Please avoid posting pictures of text. You can cut-n-paste the text from the terminal.use the ui button that looks like </> to do this.

Just
     Like
          This
3 Likes

Aside from breaking 20+ years of code, 1./0. = inf is not always the wanted result eg.

sinc(x) = sin(x)/x = 1. if x == 0. else sin(x)/x

Calculating this traping zero divide is slightly faster than chcking x != 0. eg.

def sinc(x):
  try:
     return sin(x)/x
  except ZeroDivisionError : 
     return 1.

If I was programming in C or FORTRAN the checking x == 0. is the way to go as the overhead is lower.

But… sin(0) is 0, not 1. The 0/0 indeterminate form is different.

1 Like

yes, but sin(x)/x → 1 as x → 0, easy to see if you expand sin(x) as a polynomial, so x = 0 is special.

1 Like

Strong Negative for the change, as tons of code would break for no reason.

IEEE 754 defines float point exceptions, and this is what we usually expect in C.

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_handle.html

When trap is enabled, All of these calculations will raise SIGFPE. The reason is explained in that page. I think Python should keep the behavior as is.

3 Likes

After hours of reviewing, I have created a fork repo of CPython and committed the problem we discussed.

You can see here to see what are the changes, how these affect to the Python 3.

I’m surprised [division using IEEE float semantics] is not already the behavior!

2 Likes

Honestly, sinc(x) is the very special form of math module, since math module doesn’t have sinc(x).

image

You can use this code:

def sinc(x): if x == 0: return 1 else: return math.sin(x)/x

When the x approach to 0 in sinc(x), the result of sinc(x) is just nearly 0. But when x=0, sinc(x) = 1

I hope there will be some changes applying in the future with the math module, with sinc(x) function.

1 Like

Hi all, final of the day.

Some requirement you can see below (these are all recommended by me):

  • These changes are only applied on Python 3.13 or later. Python 3.12 (all version, and earlier) are intact. :grinning:
  • The system must have at least 4Kb of RAM free. :laughing:

You can see my changes here (duplicated, I know): Comparing python:main...takineko-tfs:main · python/cpython · GitHub

If you want to apply these codes, you can click the heart :heart:.

1 Like

And click :heart: here if you do not want this in python.

15 Likes

Hi all,

If you don’t want to make these changes, let me know for the reason below.

Thanks all.

  1. Not backwards compatible. Changing how division by zero behaves would break existing code.

  2. Mathematically wrong. In general, a / 0 is not inf, from a mathematical point of view. a / 0 is undefined. lim(x->0) a / x == inf for certain values of a, but lim(x->0) a / x != a / 0.

  3. Most importantly, IMO, inf is significantly less useful than ZeroDivisionError in most cases. If I’m working on a piece of code and accidentally introduce a zero-valued denominator, I want to know that. If division of zero instead just produced inf,

    1. the inf may propagate further through the program, causing it to break in a hard-to-predict fashion somewhere else.
    2. I wouldn’t immediately know what went wrong even if I did catch the inf where it first appeared, because division by zero is not the only operation that could produce inf.
11 Likes