This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: OverflowError in division: wrong message
Type: behavior Stage:
Components: Versions: Python 3.3, Python 3.4
process
Status: closed Resolution: postponed
Dependencies: Superseder:
Assigned To: Nosy List: christian.heimes, marco.buttu, mark.dickinson, terry.reedy
Priority: normal Keywords:

Created on 2013-07-27 11:31 by marco.buttu, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Messages (9)
msg193783 - (view) Author: Marco Buttu (marco.buttu) * Date: 2013-07-27 11:31
When the integer division result is too large to converto to float, and the operands are inside the limits, the result is `inf` or `-inf`::

    >>> 2**1023 / 2**-3
    inf
    >>> 2**1022 / 2**-4
    inf
    >>> 2**1023 / 2**-1074
    inf

When both the result and an operand are too large to converto to float, we raise an OverflowError::

    >>> 2**1028 / 2**-2
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    OverflowError: long int too large to convert to float

The message says: "long int too large to convert to float". I think in Python 3 it should be "int too large to convert...". In any case, the most important thing is that in the same situation we get a different message [1]_::

    >>> 2**1032 / 2**2
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
    OverflowError: integer division result too large for a float

and I think is it muddleheaded, because it should be "long int too large to convert to float", as we got in the case `2**1028 / 2**-2`. I think we should never show "integer division result too large for a float", but just:

* `inf` or `-inf` when the operands are inside the limits, but the result 
  does not
* `OverflowError: long int too large to convert to float` when the result, 
  and at least one operand, are out of range.


.. [1] In this situation, we get the message "OverflowError: integer division result too large for a float" only when the denominator exponent is positive.
msg193793 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-07-27 20:30
Yes, 'long int' should just be 'int' in 3.x.

However, int/int (integer division) is *not* the same thing as int/float. In the latter case, the int is converted to float first and if that conversion fails, there is no result.

Now that int/int is always converted to float, it seems sensible that out of float range results be +-inf. But there may be an issue with back compatibility. I know there has been discussion on overflow vs. inf in various contexts.
msg193901 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-07-29 20:35
I'd prefer to keep the current behaviour for int / int with an out-of-range result (i.e., raise OverflowError).  As far as possible, I believe Python should raise an exception rather than return an infinity or nan whenever possible (with exceptions when one or other of the operands was an infinity or nan to begin with).  The math module does this consistently;  but (mostly for historical reasons) the core of Python doesn't have a lot of consistency w.r.t. overflow versus infinities:

Still, my own preference would be to try to move to greater use of exceptions rather than to greater use of 'inf' and 'nan' results.  So if anything, 2**1023 / 2**-3 would ideally raise OverflowError rather than return 'inf'.

Note that 1 / 0 also currently raises an exception rather than returning an infinity.

Agreed that 'long int' should be 'int'.
msg193910 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-07-29 21:46
+-infinity and nans were created for reasons that do not apply to standard python. In Fortran, C, etcetera, float arrays can only contain floats (hence calling a non-number a float) and continuing a computation after numerical error is more difficult or impossible. So something as simple as the following is not possible.

<initialize 1000 x 1000 data array>
for time in range(1, 1000):
  for x in range(1000):
    for y in range(1000):
      try:
        data[x][y] = <update>
      except Exception as e:
        data[x][y] = None  # will propagate just like NaNs!

I think we might be better with two consistently behaving float classes: proper Python floats with no inf or nan, just exceptions; and ieee floats, similar to Decimals, with as complete implementation of the ieee standard as possible, including various nan types and access to FPU flags. What we have now is a compromise that I doubt is truly satisfactory to anyone.
msg193916 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-07-30 07:47
> I think we might be better with two consistently behaving float classes

That sounds a bit extreme.  Personally, I'd look for a solution involving only one float class and a "with float.nonstopmode: ..." setting under which we get infinities and nans as prescribed by IEEE 754;  the default would be to produce exceptions in places where IEEE 754 would signal a floating-point exception (any of divide-by-zero, overflow or invalid-operation, but not for inexact or underflow).  This is definitely PEP territory, though;  and someone needs to undertake to implement it, which is distinctly nontrivial.

For this issue, I'd avoid making any small changes to current behaviour without having at least a clear vision set out of where we want to end up.
msg193941 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-07-30 17:59
I would prefer one type too, if it can be done gracefully enough. I had thought of a set-mode function (method), but anticipate objection to such modal action-at-distance behavior. A context manager, which I had not thought of, somewhat alleviates that objection, though not entirely. If code written in try-except manner is imported and run under the context manager, it might or might not work. My toy example would, in that the final array might contain Nans rather than Nones, which would be all right since the user would anticipate that, having asked for that. But if the imported code used exceptions to switch algorithms, switching from exceptions to inf/nan might not work so well.

Consistently replacing 'return inf/nan' and 'raise FPException' (where appropriate) with "if flag: return inf/nam; else: raise FPException" seems not too difficult ;-). But yes, a PEP rather than more piecemeal changes.
msg194248 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-08-03 11:09
Exception message fixed in revision dab7d6f33b87
msg194291 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-08-03 19:02
With that fixed, I am inclined to close this.
msg194328 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-08-04 07:30
> With that fixed, I am inclined to close this.

Agreed.  I'll try to find some time for a PEP at some point in the next few weeks.

> I had thought of a set-mode function (method), but anticipate objection
> to such modal action-at-distance behavior.

Yes;  I'm not a big fan of global state[*] either in general, but there aren't many other good options:  specifying the mode to each operation individually would be painful and prevent natural use of infix operators, generally making code more unreadable.  There *would* need to be some kind of set-mode function (or perhaps writable sys module attribute) as you suggest, but the context manager could be promoted as the recommended way to change the state in a manner that's reasonably safe and explicit.


[*] We'd want it to be thread-local rather than global, of course.
History
Date User Action Args
2022-04-11 14:57:48adminsetgithub: 62770
2013-08-04 07:31:07mark.dickinsonsetstatus: open -> closed
resolution: postponed
2013-08-04 07:30:24mark.dickinsonsetmessages: + msg194328
2013-08-03 19:02:15terry.reedysetmessages: + msg194291
2013-08-03 11:09:29mark.dickinsonsetmessages: + msg194248
2013-07-30 17:59:58terry.reedysetmessages: + msg193941
2013-07-30 07:47:59mark.dickinsonsetmessages: + msg193916
2013-07-29 21:46:31terry.reedysetmessages: + msg193910
2013-07-29 20:35:33mark.dickinsonsetmessages: + msg193901
2013-07-27 20:30:29terry.reedysetnosy: + terry.reedy
messages: + msg193793
2013-07-27 19:43:27marco.buttusettitle: OverflowError during division: wrong message -> OverflowError in division: wrong message
2013-07-27 11:32:35christian.heimessetnosy: + mark.dickinson, christian.heimes

versions: - Python 3.1, Python 3.2
2013-07-27 11:31:25marco.buttucreate