10

The // "integer division" operator of Python surprised me, today:

>>> math.floor(11/1.1)
10.0
>>> 11//1.1
9.0

The documentation reads "(floored) quotient of x and y". So, why is math.floor(11/1.1) equal to 10, but 11//1.1 equal to 9?

smci
  • 32,567
  • 20
  • 113
  • 146
Eric O. Lebigot
  • 91,433
  • 48
  • 218
  • 260
  • 5
    http://mail.python.org/pipermail/python-dev/2007-January/070707.html – miku Jan 07 '10 at 10:40
  • The canonical question for Python 2-vs-3 division difference is [How can I force division to be floating point in Python? Division keeps rounding down to 0](https://stackoverflow.com/questions/1267869/how-can-i-force-division-to-be-floating-point-in-python-division-keeps-rounding) – smci Oct 14 '16 at 05:15

1 Answers1

7

Because 1.1 can't be represented in binary form exactly; the approximation is a littler higher than 1.1 - therefore the division result is a bit too small.

Try the following:

Under Python 2, type at the console:

>>> 1.1
1.1000000000000001

In Python 3.1, the console will display 1.1, but internally, it's still the same number.

But:

>>> 11/1.1
10.0

As gnibbler points out, this is the result of "internal rounding" within the available precision limits of floats. And as The MYYN points out in his comment, // uses a different algorithm to calculate the floor division result than math.floor() in order to preserve a == (a//b)*b + a%b as well as possible.

Use the Decimal type if you need this precision.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • But according to Python `11.0/1.1 == 10.0` is true – sth Jan 07 '10 at 10:40
  • 1
    As we know 1.1 is stored as 1.1000000000000001, so the result 11.0/1.1 in Python is 9.999999999999999090909090909 but the closest float to this number is infact 10.0, so it happens that the result is exactly 10.0 – John La Rooy Jan 07 '10 at 11:22
  • @Tim I thought of that, and I believe this is the key to the difference between math.floor(11/1.1) and 11//1.1. However, as gnibbler pointed out, the fact that 1.1 is represented by a slightly larger number only indicates that math.floor(11/1.1) should really be 9.0, which leaves the original question still open. – Eric O. Lebigot Jan 07 '10 at 12:45
  • 1
    @EOL, since 11/1.1 evaluates to exactly 10.0, math.floor(11/1.1)=math.floor(10.0), however this is only due to some luck with the rounding – John La Rooy Jan 07 '10 at 22:36
  • 1
    @gnibbler: Yeah, it's the "luck" aspect that surprised me: two "identical" operations behaving in a different way. :) The explanation is in the implementation, as pointed out by The MYYN. – Eric O. Lebigot Jan 08 '10 at 12:58