Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #77946 > unrolled thread

Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))`

Started bycool-RR <ram.rachum@gmail.com>
First post2014-09-16 14:40 -0700
Last post2014-09-18 23:48 -0700
Articles 11 on this page of 31 — 9 participants

Back to article view | Back to comp.lang.python


Contents

  Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` cool-RR <ram.rachum@gmail.com> - 2014-09-16 14:40 -0700
    Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Terry Reedy <tjreedy@udel.edu> - 2014-09-16 21:12 -0400
      Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` cool-RR <ram.rachum@gmail.com> - 2014-09-17 07:55 -0700
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 01:10 +1000
          Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` cool-RR <ram.rachum@gmail.com> - 2014-09-17 08:16 -0700
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 01:29 +1000
              Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` cool-RR <ram.rachum@gmail.com> - 2014-09-17 09:33 -0700
                Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 02:37 +1000
                Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-09-18 13:11 +1000
                  Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` cool-RR <ram.rachum@gmail.com> - 2014-09-18 01:43 -0700
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-17 09:34 -0600
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 01:40 +1000
              Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-09-18 12:50 +1000
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-17 10:12 -0600
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-17 10:30 -0600
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-17 12:03 -0600
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 07:37 +1000
          Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-09-18 13:29 +1000
            Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Chris Angelico <rosuav@gmail.com> - 2014-09-18 13:47 +1000
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Terry Reedy <tjreedy@udel.edu> - 2014-09-17 19:23 -0400
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-18 00:51 -0600
    Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-17 09:35 -0600
    Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` wxjmfauth@gmail.com - 2014-09-17 23:22 -0700
      Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Marko Rauhamaa <marko@pacujo.net> - 2014-09-18 09:45 +0300
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` wxjmfauth@gmail.com - 2014-09-18 00:13 -0700
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-09-18 19:25 +1000
          Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` wxjmfauth@gmail.com - 2014-09-18 05:57 -0700
          Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Grant Edwards <invalid@invalid.invalid> - 2014-09-18 14:33 +0000
      Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` chris.barker@noaa.gov - 2014-09-18 09:35 -0700
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` Ian Kelly <ian.g.kelly@gmail.com> - 2014-09-18 11:05 -0600
        Re: Why `divmod(float('inf'), 1) == (float('nan'), float('nan'))` wxjmfauth@gmail.com - 2014-09-18 23:48 -0700

Page 2 of 2 — ← Prev page 1 [2]


#78002

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-09-18 00:51 -0600
Message-ID<mailman.14098.1411023134.18130.python-list@python.org>
In reply to#77964
On Wed, Sep 17, 2014 at 3:37 PM, Chris Angelico <rosuav@gmail.com> wrote:
> It's not something I've personally worked with, so I'm trying to
> dredge stuff up from my brain, but I think there's something along the
> lines of "stuff shouldn't be a multiple of everything" and the Prime
> Number Theorem. But that may just be a case where float != real.

Certainly no finite number can be a multiple of everything. Are you
perchance thinking of the proof of Euclid's theorem?

[toc] | [prev] | [next] | [standalone]


#77970

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-09-17 09:35 -0600
Message-ID<mailman.14079.1410968195.18130.python-list@python.org>
In reply to#77946
On Tue, Sep 16, 2014 at 7:12 PM, Terry Reedy <tjreedy@udel.edu> wrote:
> It does not really matter, however, as infinity cannot be 'floored' as
> required for //
>
>>>> math.floor(float('inf'))
> Traceback (most recent call last):
>   File "<pyshell#21>", line 1, in <module>
>     math.floor(float('inf'))
> OverflowError: cannot convert float infinity to integer
>
> and hence
>
>>>> float('inf') // 1.0
> nan

In C, floor(INFINITY) returns infinity (at least in the implementation
I just tested).

[toc] | [prev] | [next] | [standalone]


#78000

Fromwxjmfauth@gmail.com
Date2014-09-17 23:22 -0700
Message-ID<cd5f2ac9-4b8f-446e-9b94-ec7af6212d03@googlegroups.com>
In reply to#77946
Le mardi 16 septembre 2014 23:40:44 UTC+2, cool-RR a écrit :
> While debugging my code I found that the bug was because I assumed that something like `divmod(float('inf'), 1)` would be equal to `(float('inf'), float('nan'))`, while Python returns `(float('nan'), float('nan'))`. Why does Python make the division result be NaN in this case? `float('inf') / 1` is still `float('inf')`.
> 

On one side, it is very nice, Python offers this
"non finite arithmetic" (just to give a name).
But on the other side it is also a plague: one
never knows how to handle calculations properly.
In an application which pretends to be solid, it's
necessary to duplicate the checkings in a unnecessary
way.

In short, a lack of consistency.

>>> 1e300*1e300
inf
>>> exp(1e300)
Traceback (most recent call last):
  File "<eta last command>", line 1, in <module>
OverflowError: math range error
>>>

jmf

[toc] | [prev] | [next] | [standalone]


#78001

FromMarko Rauhamaa <marko@pacujo.net>
Date2014-09-18 09:45 +0300
Message-ID<87sijp5swd.fsf@elektro.pacujo.net>
In reply to#78000
wxjmfauth@gmail.com:

> In short, a lack of consistency.
>
>>>> 1e300*1e300
> inf
>>>> exp(1e300)
> Traceback (most recent call last):
>   File "<eta last command>", line 1, in <module>
> OverflowError: math range error

Good point!

Maybe IEEE had some specific numeric algorithms in mind when it
introduced inf and nan. However, I have a feeling an exception would be
a sounder response whenever the arithmetics leaves the solid ground.


Marko

[toc] | [prev] | [next] | [standalone]


#78003

Fromwxjmfauth@gmail.com
Date2014-09-18 00:13 -0700
Message-ID<3c75b14e-0d87-47dc-b626-e9d5fffc9cbc@googlegroups.com>
In reply to#78001
Le jeudi 18 septembre 2014 08:45:21 UTC+2, Marko Rauhamaa a écrit :
> wxjmfauth@gmail.com:
> 
> 
> 
> > In short, a lack of consistency.
> 
> >
> 
> >>>> 1e300*1e300
> 
> > inf
> 
> >>>> exp(1e300)
> 
> > Traceback (most recent call last):
> 
> >   File "<eta last command>", line 1, in <module>
> 
> > OverflowError: math range error
> 
> 
> 
> Good point!
> 
> 
> 
> Maybe IEEE had some specific numeric algorithms in mind when it
> 
> introduced inf and nan. However, I have a feeling an exception would be
> 
> a sounder response whenever the arithmetics leaves the solid ground.
> 
> 
Nothing to do with IEEE. It's a pure Python question.

If Python is using its own algorithmics for some "type
of numbers" and at the same time it uses (or it has to use)
a C library with a different algorithmics, conflicts are
expected.

In my previous example, both solutions are valid. The
both solutions at the same time -> problem.

jmf

[toc] | [prev] | [next] | [standalone]


#78008

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2014-09-18 19:25 +1000
Message-ID<541aa526$0$29993$c3e8da3$5496439d@news.astraweb.com>
In reply to#78001
Marko Rauhamaa wrote:

> Maybe IEEE had some specific numeric algorithms in mind when it
> introduced inf and nan. However, I have a feeling an exception would be
> a sounder response whenever the arithmetics leaves the solid ground.

I'm afraid that you're missing the essential point of INF and quiet NANs,
namely that they *don't* cause an exception. That is their point.

Back in the Dark Ages of numeric computing, prior to IEEE-754, all was
chaos. Numeric computing was a *mess*. To give an example of how bad it
was, there were well-known computers where:

    x != 0

would pass, but then:

    1.0/x

would fail with a Division By Zero error (which could mean a segfault).
Another machine could have 1.0*x overflow; a whole class of IBM machines
had 1.0*x lop off one bit of precision each time you called it, so that
multiplying by one would gradually and irreversibly change the number. Chip
designers had a cavalier attitude towards the accuracy of floating point
arithmetic, preferring to optimise for speed even when the result was
wrong. Writing correct, platform-independent floating point code was next
to impossible.

When IEEE-754 was designed, the target was low-level languages similar to C,
Pascal, Algol, Lisp, etc. There were no exceptions in the Python sense, but
many platforms provided signals, where certain operations could signal an
exceptional case and cause an interrupt. IEEE-754 standardised those
hardware-based signals and required any compliant system to provide them.

But it also provided a mechanism for *not* interrupting a long running
calculation just because an exception occurred. Remember that not all
exceptions are necessarily fatal. You can choose whether exceptions in a
calculation will cause a signal, or quietly continue. It even defines two
different kinds of NANs, signalling and quiet NANs: signalling NANs are
supposed to signal, always, and quiet NANs are supposed to either silently
propagate or signal, whichever you choose.

Instead of peppering your code with dozens, even hundreds of Look Before You
Leap checks for error conditions, or installing a single signal handler
which will catch exceptions from anywhere in your application, you have the
choice of also allowing calculations to continue to the end even if they
reach an exceptional case. You can then inspect the result and decide what
to do: report an error, re-do the calculation with different values, skip
that iteration, whatever is appropriate.

The standard even gives NANs a payload, so that they can carry diagnostic
information. For instance, NAN[1] might mean 0/0, while NAN[2] might mean
INF-INF. The Standard Apple Numerics Environment (SANE) in the 1980s and
90s supported that, and it worked really well. Alas, I don't know any other
language or library that even offers a way to inspect the NAN payload, let
alone promises to set it consistently.

In any case, other error handling strategies continue to work, or at least
they are supposed to work.

A good way to understand how the IEEE-754 standard is supposed to work is to
read and use the decimal.py module. (Strictly speaking, decimal doesn't
implement IEEE-754, but another, similar, standard.) Python's binary
floats, which are a thin wrapper around the platform C libraries, is sad
and impoverished compared to what IEEE-754 offers.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#78012

Fromwxjmfauth@gmail.com
Date2014-09-18 05:57 -0700
Message-ID<e434fb7c-091a-41a0-b61b-cb1db3976456@googlegroups.com>
In reply to#78008
Le jeudi 18 septembre 2014 11:26:14 UTC+2, Steven D'Aprano a écrit :
> Marko Rauhamaa wrote:
> 
> 
> 
> > Maybe IEEE had some specific numeric algorithms in mind when it
> 
> > introduced inf and nan. However, I have a feeling an exception would be
> 
> > a sounder response whenever the arithmetics leaves the solid ground.
> 
> 
> 
> I'm afraid that you're missing the essential point of INF and quiet NANs,
> 
> namely that they *don't* cause an exception. That is their point.
> 
> 
> 
> Back in the Dark Ages of numeric computing, prior to IEEE-754, all was
> 
> chaos. Numeric computing was a *mess*. To give an example of how bad it
> 
> was, there were well-known computers where:
> 
> 
> 
>     x != 0
> 
> 
> 
> would pass, but then:
> 
> 
> 
>     1.0/x
> 
> 
> 
> would fail with a Division By Zero error (which could mean a segfault).
> 
> Another machine could have 1.0*x overflow; a whole class of IBM machines
> 
> had 1.0*x lop off one bit of precision each time you called it, so that
> 
> multiplying by one would gradually and irreversibly change the number. Chip
> 
> designers had a cavalier attitude towards the accuracy of floating point
> 
> arithmetic, preferring to optimise for speed even when the result was
> 
> wrong. Writing correct, platform-independent floating point code was next
> 
> to impossible.
> 
> 
> 
> When IEEE-754 was designed, the target was low-level languages similar to C,
> 
> Pascal, Algol, Lisp, etc. There were no exceptions in the Python sense, but
> 
> many platforms provided signals, where certain operations could signal an
> 
> exceptional case and cause an interrupt. IEEE-754 standardised those
> 
> hardware-based signals and required any compliant system to provide them.
> 
> 
> 
> But it also provided a mechanism for *not* interrupting a long running
> 
> calculation just because an exception occurred. Remember that not all
> 
> exceptions are necessarily fatal. You can choose whether exceptions in a
> 
> calculation will cause a signal, or quietly continue. It even defines two
> 
> different kinds of NANs, signalling and quiet NANs: signalling NANs are
> 
> supposed to signal, always, and quiet NANs are supposed to either silently
> 
> propagate or signal, whichever you choose.
> 
> 
> 
> Instead of peppering your code with dozens, even hundreds of Look Before You
> 
> Leap checks for error conditions, or installing a single signal handler
> 
> which will catch exceptions from anywhere in your application, you have the
> 
> choice of also allowing calculations to continue to the end even if they
> 
> reach an exceptional case. You can then inspect the result and decide what
> 
> to do: report an error, re-do the calculation with different values, skip
> 
> that iteration, whatever is appropriate.
> 
> 
> 
> The standard even gives NANs a payload, so that they can carry diagnostic
> 
> information. For instance, NAN[1] might mean 0/0, while NAN[2] might mean
> 
> INF-INF. The Standard Apple Numerics Environment (SANE) in the 1980s and
> 
> 90s supported that, and it worked really well. Alas, I don't know any other
> 
> language or library that even offers a way to inspect the NAN payload, let
> 
> alone promises to set it consistently.
> 
> 
> 
> In any case, other error handling strategies continue to work, or at least
> 
> they are supposed to work.
> 
> 
> 
> A good way to understand how the IEEE-754 standard is supposed to work is to
> 
> read and use the decimal.py module. (Strictly speaking, decimal doesn't
> 
> implement IEEE-754, but another, similar, standard.) Python's binary
> 
> floats, which are a thin wrapper around the platform C libraries, is sad
> 
> and impoverished compared to what IEEE-754 offers.
> 
> 
> 
> 

>>> def docalc1(i):
...     if i == 0:
...         t = 1 / 0
...     else:
...         return float('inf')
...         
>>> try:
...     r = docalc1(1)
...     if math.isinf(r):
...         print('do something because inf')
... except ZeroDivisionError:
...     print('do something else because error is raised')
...     
do something because inf
>>> try:
...     r = docalc1(0)
...     if math.isinf(r):
...         print('do something because inf')
... except ZeroDivisionError:
...     print('do something else because error is raised')
...     
do something else because error is raised


Annoying. One does not know the result *before*
executing any calculations.

jmf

[toc] | [prev] | [next] | [standalone]


#78017

FromGrant Edwards <invalid@invalid.invalid>
Date2014-09-18 14:33 +0000
Message-ID<lveqf7$fns$1@reader1.panix.com>
In reply to#78008
On 2014-09-18, Steven D'Aprano <steve+comp.lang.python@pearwood.info> wrote:
> Marko Rauhamaa wrote:
>
>> Maybe IEEE had some specific numeric algorithms in mind when it
>> introduced inf and nan. However, I have a feeling an exception would be
>> a sounder response whenever the arithmetics leaves the solid ground.
>
> I'm afraid that you're missing the essential point of INF and quiet NANs,
> namely that they *don't* cause an exception. That is their point.

And it is a very important point.  I spent a number of years working
with floating point in process control where the non-signalling
(propogating) behavior of IEEE inf and NaNs was exactly the right
thing.

You've got a set of inputs, and a set of outputs each of which depend
on some (but not usually all of the inputs).  When one of the inputs
goes invalid (NaN) or wonky (creating an infinity), it's vitally
important that the computations _all_ got carried out and _all_ of the
outputs got calculated and updated.  Not updating an output was simply
not an option.

Some outputs end up as NaNs or infinities and some are valid, but
_all_ of them get set to the proper value for the given set of inputs.

Using exceptions would have required a whole "shadow" set of
calculations and logic to try to figure out which outputs were still
valid and could be calculated, and which ones were not valid.  It
would have at least tripled the amount of code required -- and it
probably wouldn't have worked right.

-- 
Grant Edwards               grant.b.edwards        Yow! My mind is a potato
                                  at               field ...
                              gmail.com            

[toc] | [prev] | [next] | [standalone]


#78023

Fromchris.barker@noaa.gov
Date2014-09-18 09:35 -0700
Message-ID<1f3b8ce6-614a-4b99-9660-a6ef35eda75f@googlegroups.com>
In reply to#78000
On Wednesday, September 17, 2014 11:22:42 PM UTC-7, wxjm...@gmail.com wrote:
> >>> 1e300*1e300
> 
> inf
> 
> >>> exp(1e300)
> 
> Traceback (most recent call last):
> 
>   File "<eta last command>", line 1, in <module>
> 
> OverflowError: math range error

FWIW, numpy is a bit more consistent:

In [89]: numpy.exp(1e300)
Out[89]: inf

This is more critical in numpy, because that result may have been one of a big huge array of values -- you really don't want the entire array operation to raise and Exception because of one odd value.

It's be nice if Python's math module did more than simply wrap the default i implementation of the underlying C lib -- it's gotten better over the years (Inf and NaN used to be really hard to get), but still not quite what it could be.

-Chris

[toc] | [prev] | [next] | [standalone]


#78028

FromIan Kelly <ian.g.kelly@gmail.com>
Date2014-09-18 11:05 -0600
Message-ID<mailman.14112.1411060010.18130.python-list@python.org>
In reply to#78023
On Thu, Sep 18, 2014 at 10:35 AM,  <chris.barker@noaa.gov> wrote:
> It's be nice if Python's math module did more than simply wrap the default i implementation of the underlying C lib -- it's gotten better over the years (Inf and NaN used to be really hard to get), but still not quite what it could be.

I think there's not a whole lot that can be done due to backward
compatibility issues. Python 3 did make some progress (e.g. math.floor
now returns an int instead of a float).

[toc] | [prev] | [next] | [standalone]


#78062

Fromwxjmfauth@gmail.com
Date2014-09-18 23:48 -0700
Message-ID<91f47abd-6c64-459b-b87f-ef3ec5cc3980@googlegroups.com>
In reply to#78023
Le jeudi 18 septembre 2014 18:36:03 UTC+2, chris....@noaa.gov a écrit :
> On Wednesday, September 17, 2014 11:22:42 PM UTC-7, wxjm...@gmail.com wrote:
> 
> > >>> 1e300*1e300
> 
> > 
> 
> > inf
> 
> > 
> 
> > >>> exp(1e300)
> 
> > 
> 
> > Traceback (most recent call last):
> 
> > 
> 
> >   File "<eta last command>", line 1, in <module>
> 
> > 
> 
> > OverflowError: math range error
> 
> 
> 
> FWIW, numpy is a bit more consistent:
> 
> 
> 
> In [89]: numpy.exp(1e300)
> 
> Out[89]: inf
> 
> 
> 
> This is more critical in numpy, because that result may have been one of a big huge array of values -- you really don't want the entire array operation to raise and Exception because of one odd value.
> 
> 
> 
> It's be nice if Python's math module did more than simply wrap the default i implementation of the underlying C lib -- it's gotten better over the years (Inf and NaN used to be really hard to get), but still not quite what it could be.
> 
Silly argument. One single "inf" may be enough to
not pursuit any further calculations. So the only
way is to always test if one get "valid" values (values
which have a "sense")-

Example:
2-dimensional Fourier transormation. If the transformation
of the first raw (columns) return one single such value,
it's not worth to continue to calculate in "vacuum".

As I already said, this "not finite arithmetic" may
look very appealing, in many cases, it is an annoying
double sword.

Note: I wrote "Numerical Recipes" in Python. This kind
of problem is particulary accute in "linear algebra".

jmf

PS math.isinf() --> has_array_inf() ?!

[toc] | [prev] | [standalone]


Page 2 of 2 — ← Prev page 1 [2]

Back to top | Article view | comp.lang.python


csiph-web