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"?