[Python-Dev] Floor division

Guido van Rossum guido at python.org
Mon Jan 22 16:57:02 CET 2007


On 1/21/07, Tim Peters <tim.peters at gmail.com> wrote:
> [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?

No way!

> 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.

Oops, you're right. I'm suffering from memory loss. :-(

> > 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).

So you are proposing that Decimal also rip out the % and // operators
and __divmod__? WFM, but I don't know what Decimal users say (I'm not
one).

> > 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.

OK, that's good.

> 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!).

For ints and floats, real could just return self, and imag could
return a 0 of the same type as self. I guess the conjugate() function
could also just return self (although I see that conjugate() for a
complex with a zero imaginary part returns something whose imaginary
part is -0; is that intentional? I'd rather not have to do that when
the input is an int or float, what do you think?)

-- 
--Guido van Rossum (home page: http://www.python.org/~guido/)


More information about the Python-Dev mailing list