Why Python 3?
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sun Apr 20 23:43:17 EDT 2014
On Mon, 21 Apr 2014 09:24:09 +1000, Chris Angelico wrote:
> On Mon, Apr 21, 2014 at 8:52 AM, Gregory Ewing
> <greg.ewing at canterbury.ac.nz> wrote:
>> Chris Angelico wrote:
>>
>>> Truncating vs true is not the same as int vs float. If you mean to
>>> explicitly request float division, you call float() on one or both
>>> arguments. You're being explicit about something different.
>>
>>
>> If you know you're dealing with either ints or floats, which is true in
>> the vast majority of cases, then you know that / will always perform
>> float division.
>
> And that's what I mean about the common non-trivial case. It's easy
> enough to come up with contrived or trivial cases that use any types,
> but in most cases, it'd be fine to explicitly call float() on one of the
> operands to explicitly request floating-point division. Choosing between
> two division operators is not the same thing as choosing a data type.
Nobody says that they are. Choosing between / and // means to choose
between two different operator. / performs true division, the sort that
you learn about in school (modulo the usual floating point issues --
floats are not mathematical reals). // performs division which floors
towards negative infinity. (For positive values, that's equivalent to
truncation.)
Hence the two special methods: __truediv__ and __floordiv__ (plus the
reversed __r*__ versions).
I think you need to stop thinking about "integer division", because (1)
"integer division" is not well-defined, and (2) in the general case, //
doesn't return an int, although it should return a value that is integer
valued.
Why is integer division not well-defined? Because division of integers
doesn't necessarily return an integer: the integers are not closed with
the division operator. Cases like 10/5 are easy, that's just 2. What
about 11/5 or -7/3? I can think of at least six things that "integer
division" might do in those cases:
- round to nearest, ties round to even ("banker's rounding");
- round to nearest, ties round to odd;
- round towards positive infinity (ceiling);
- round towards negative infinity (floor);
- round towards zero (truncate);
- raise an exception;
so before talking about "integer division" we have to decide which of
those apply. Python doesn't talk about integer division, well not
officially, but talks about *floor division*. The nice thing about this
is that there's no requirement that it return an actual int:
py> 11.0//2
5.0
just an integer-valued value. It's up to the class to decide how it works.
> Explicitly choosing float division:
>
> x / float(y)
But here you're not choosing an *operator*, you're choosing a *type*.
With this model, how do I distinguish between floor division and true
division using, say, Fractions?
py> from fractions import Fraction as F
py> F(1799, 27)/F(3) # True division.
Fraction(1799, 81)
py> F(1799, 27)//F(3) # Floor division.
22
Converting to floats is not an option, since (1) it returns a float, not
a Fraction, and (2) it introduces rounding errors:
py> F(1799, 27)/F(3) == F(1799, 27)/3.0
False
[...]
> Both explicit forms can be done cleanly without empowering the language
> with the magic of int/int->float.
It's hardly magic, and I really am having difficult in working out
exactly what your objection to it is. Is it really as simple as
"operations on ints should only return ints, like in C"?
--
Steven D'Aprano
http://import-that.dreamwidth.org/
More information about the Python-list
mailing list