[Python-Dev] Floor division

Tim Peters tim.peters at gmail.com
Mon Jan 22 06:21:35 CET 2007


...

[Tim]
>> It's just a fact that different definitions of mod are most useful
>> most often depending on data type.  Python's is good for integers and
>> often sucks for floats.  The C99 and `decimal` definition(s) is/are
>> good for floats and often suck(s) for integers.  Trying to pretend
>> that integers are a subset of floats can't always work ;-)

[Guido]
> That really sucks, especially since the whole point of making int
> division return a float was to make the integers embedded in the
> floats... I think the best solution would be to remove the definition
> of % (and then also for divmod()) for floats altogether, deferring to
> math.fmod() instead.

In Python 2?  I thought this was already (semi)settled for Py3K --
back last May, on the Py3K list, in a near-repetition of the current
thread:

    [Tim]
    I'd be happiest if P3K floats didn't support __mod__ or __divmod__ at
    all.  Floating mod is so rare it doesn't need syntactic support, and
    the try-to-be-like-integer __mod__ and __divmod__ floats support now
    can deliver surprises to all users incautious enough to use them.

    [Guido]
    OK, this makes sense. I've added this to PEP 3100.

> The ints aren't really embedded in Decimal, so we don't have to do
> that there (but we could).

Floor division is an odd beast for floats, and I don't know of a good
use for it.  As Raymond's original example in this thread showed, it's
not always the case that

    math.floor(x/y) == x // y

The rounding error in computing x/y can cause floor() to see an exact
integer coming in even when the true value of x/y is a little smaller
than that integer (of course it's also possible for x/y to overflow).
This is independent of fp base (it's "just as true" for decimal floats
as for binary floats).

The `decimal` module also has two distinct flavors of "mod", neither
of which match Python's integer-mod definition:

>>> decimal.Decimal(7).__mod__(10)
Decimal("7")
>>> decimal.Decimal(7).remainder_near(10)
Decimal("-3")
>>> decimal.Decimal(-7).__mod__(10)
Decimal("-7")
>>> decimal.Decimal(-7).remainder_near(10)
Decimal("3")

But, again, I think floating mod is so rare it doesn't need syntactic
support, and especially not when there's more than one implementation
-- and `decimal` is a floating type (in Cowlishaw's REXX, this was the
/only/ numeric type, so there was more pressure there to give it a
succinct spelling).

> The floats currently aren't embedded in complex, since f.real and
> f.imag don't work for floats (and math.sqrt(-1.0) doesn't return 1.0j,
> and many other anomalies). That was a conscious decision because
> complex numbers are useless for most folks. But is it still the right
> decision, given what we're trying to do with int and float?

Sounds like a "purity" thing.  The "pure form" of the original
/intent/ was probably just that nobody should get a complex result
from non-complex inputs (they should see an exception instead) unless
they use a `cmath` function to prove they know what they're doing up
front.

I still think that has pragmatic value, since things like sqrt(-1) and
asin(1.05) really are signs of logic errors for most programs.

But under that view, there's nothing surprising about, e.g.,
(math.pi).imag returning 0.0 -- or (3).imag returning 0.0 either.
That sounds fine to me (if someone cares enough to implement it).
Unclear what very_big_int.real should do (it can lose information to
rounding if the int > 2**53, or even overflow -- maybe it should just
return the int!).


More information about the Python-Dev mailing list