2

I'm not sure how integer division actually works with decimal. Considering these two examples on Python 3.x:

4/0.4 = 10.0
4//0.4 = 9.0

Regular division gives 10 but the integer division of 4 by 0.4 results in 9.0.

Do you know the behavior of integer division with decimal and why the result is this way?

jia Jimmy
  • 1,693
  • 2
  • 18
  • 38
Au Vo
  • 47
  • 2
  • 2
    `//` is floor division, not "integer division". – user2357112 Feb 18 '19 at 06:12
  • 1
    According to [the official Python 3 reference](https://docs.python.org/3/reference/expressions.html#binary-arithmetic-operations) the `//` operator is *floor division*, not integer division (how would an integer division using non-integer values even work?). As for the result, see [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken). – Some programmer dude Feb 18 '19 at 06:12
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – Andras Deak -- Слава Україні Feb 18 '19 at 06:19
  • Combine with https://stackoverflow.com/questions/183853/what-is-the-difference-between-and-when-used-for-division for full effect. – Andras Deak -- Слава Україні Feb 18 '19 at 06:21
  • Possible duplicate of [What is the difference between '/' and '//' when used for division?](https://stackoverflow.com/questions/183853/what-is-the-difference-between-and-when-used-for-division) – Felix Martinez Feb 18 '19 at 08:28

1 Answers1

1

The CPython's implementation of floor division of a float number, as either a dividend or a divisor, lies in the float_floor_div function, which calls the float_divmod function (which implements the divmod function) for the actual calculation, which, with the following lines of code:

mod = fmod(vx, wx);
div = (vx - mod) / wx;
...
floordiv = floor(div);

tells you that the way that floor division works for a float number is to first call the fmod function to obtain the remainder of the division, subtract the remainder from the dividend vx, and then divide it by the divisor wx, before applying the floor function on the resulting quotient div.

And if you try performing the modulo operation of 4 % 0.4, expecting it to be 0 because 4 / 0.4 should be mathematically 10:

>>> 4 % 0.4
0.3999999999999998

You'll see the classic floating error inherent from the way decimal numbers are approximated by the binary system. As a result 0.4 is actually stored as something slightly greater than 0.4, which you can verify by instantiating a high-precision Decimal object with 0.4:

>>> from decimal import Decimal
>>> Decimal(0.4)
Decimal('0.40000000000000002220446049250313080847263336181640625')

which is why 4 % 0.4 has a remainder of 0.3999999999999998 instead of 0, and as a result, with the way float_divmod calculated the quotient, by first subtracting the remainder from the dividend, you get:

>>> 4 - 4 % 0.4
3.6

so naturally,

>>> (4 - 4 % 0.4) / 0.4
9.0
blhsing
  • 91,368
  • 6
  • 71
  • 106