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

Ian Kelly ian.g.kelly at gmail.com
Wed Sep 17 18:12:18 CEST 2014

On Wed, Sep 17, 2014 at 9:40 AM, Chris Angelico <rosuav at gmail.com> wrote:
> On Thu, Sep 18, 2014 at 1:34 AM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
>> On Wed, Sep 17, 2014 at 9:29 AM, Chris Angelico <rosuav at gmail.com> wrote:
>>> On Thu, Sep 18, 2014 at 1:16 AM, cool-RR <ram.rachum at gmail.com> wrote:
>>>> I didn't ask for the modulo, I agree it should remain NaN. I'm talking about the floor division.
>>> Invariant: div*y + mod == x.
>>> If mod is NaN, there is no possible value for div that will make the
>>> invariant true, ergo it too has to be NaN.
>> That still doesn't make the invariant true. By this argument div could
>> be 42, and the invariant would hold equally well (i.e. not at all).
> Nothing can possibly make it true, so there are only two
> possibilities: return NaN, or raise an exception.

I could see raising an exception, since the docs state "the result is
(q, a % b), where q is usually math.floor(a / b) but may be 1 less
than that" and it's already been established that
math.floor(float('inf')) raises an exception (although interesting
note: in Python 2 the docs claimed the same thing, but
math.floor(float('inf')) returned float('inf') and divmod already
returned float('nan'); so I don't think that the behavior of
math.floor is really the origin of this).

But the point I'm trying to make is that returning NaN here is every
bit as arbitrary as returning None or False, because there *is* a
value that makes actual mathematical sense to return, even if it fails
to maintain the invariant on account of the modulus addition (which
should just be omitted in this case).

Here's another edge case that fails the invariant. Why should divmod
return inf here but not in the first case?

>>> divmod(1e300, 1e-300)
(inf, 4.891554850853602e-301)
>>> _[0] * 1e-300 + _[1]

More information about the Python-list mailing list