[Python-ideas] Fwd: Make `float('inf') //1 == float('inf')`
Case Van Horsen
casevh at gmail.com
Fri Sep 19 00:57:29 CEST 2014
On Thu, Sep 18, 2014 at 12:31 PM, Alexander Belopolsky
<alexander.belopolsky at gmail.com> wrote:
>
> On Thu, Sep 18, 2014 at 1:27 PM, Case Van Horsen <casevh at gmail.com> wrote:
>>
>> The ISO C99/C11 (Annex F) (and POSIX and IEEE-754) standards define
>> a function called "roundToIntegralTowardsNegative". For the special value
>> +Inf, it specifies a return value of +Inf.
>>
>> However, the integral value returned is still an IEEE-754 formatted value
>> and can return +Inf. PEP-3141 changed the behavior of math.floor() (and
>> __floor__ in general) to return an actual integer. That makes it
>> impossible
>> to comply with ISO etc. standards.
>
>
> I don't think there is any dispute over what math.floor(inf) should return.
> POSIX, C99, IEEE and probably many other standards agree that inf should be
> returned as long as the resulting type can represent it.
I dispute that there is no dispute over what math.floot(inf) should return. ;-)
All the standards specify a result type can represent +-Inf and +-0. A
standards compliant version should return +-Inf and +-0. lrint() and llrint()
are defined to return long or long long, respectively. It would be fine if
they raised an exception. The current math.floor() actually behaves more
like llrint() than floor().
I accpet that having math.floor() return an integer (and raise an exception
for +-Inf) may be useful in many cases but it is different from the standard.
Other floating-point libraries still return a floating-point value.
>>> numpy.floor(numpy.float64('Inf'))
inf
>>> mpmath.floor(mpmath.mpf('inf'))
mpf('+inf')
>>> gmpy2.floor(gmpy2.mpfr('inf'))
mpfr('inf')
>>> bigfloat.floor(bigfloat.BigFloat('inf'))
BigFloat.exact('Infinity', precision=53)
Disclaimer: I maintain gmpy2.
>
> Note that before math.floor() was changed to return int in 3.x, we had
>
>>>> math.floor(float('inf'))
> inf
>
> (Python 2.7.8)
>
> The question here is not about floor, but about floor_division. NumPy
> implements it as simple-minded floor(x/y), while Python attempts to be more
> precise by doing floor((x - fmod(x, y))/y).
>
>
> $ hg blame -d -u -w Objects/floatobject.c
> nascheme Thu Jan 04 01:44:34 2001 +0000: float_divmod(PyObject *v,
> PyObject *w)
> ..
> guido Sun Oct 20 20:16:45 1991 +0000: mod = fmod(vx, wx);
> tim Sat Sep 16 03:54:24 2000 +0000: /* fmod is typically exact,
> so vx-mod is *mathematically* an
> guido Thu May 06 14:26:34 1999 +0000: exact multiple of wx. But
> this is fp arithmetic, and fp
> guido Thu May 06 14:26:34 1999 +0000: vx - mod is an
> approximation; the result is that div may
> guido Thu May 06 14:26:34 1999 +0000: not be an exact integral
> value after the division, although
> guido Thu May 06 14:26:34 1999 +0000: it will always be very
> close to one.
> guido Thu May 06 14:26:34 1999 +0000: */
> guido Sun Oct 20 20:16:45 1991 +0000: div = (vx - mod) / wx;
> ..
>
> Given that this logic dates back to 1991, I doubt not-finite case was
> seriously considered.
>
> In light of PEP 3141, if anything should be done about float // float it
> would be to make it return and int and as a consequence inf // 1 should
> raise an OverflowError.
Since divmod() and floor_division aren't defined by a standard, Python
can define its own standard. But each time Python changes behavior,
external libraries will need to change, or not; and another difference
between Python versions is introduced.
More information about the Python-ideas
mailing list