2

I have just started python tutorials. Why does

print  int (100*(11.20 - 11))

print 19 instead of 20 in python ?? There is some sort of rounding off done by integer but i am unable to catch that. Help is appreciated.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
Kirty Bhushan
  • 147
  • 2
  • 12
  • 1
    not to mention that `print 100*(11.20 - 11)` echoes `20.0` – njzk2 Jan 05 '15 at 20:13
  • Duplicate of http://stackoverflow.com/questions/588004/is-floating-point-math-broken – dwn Jan 05 '15 at 20:18
  • @dwn Actually, if you want to be technical about it, in that question the problem is that `+` is not exact, whereas in this question the problem is that `11.20` is not exactly `1120/100` and, if I'm not mistaken, all floating-point operations are exact. – Pascal Cuoq Jan 05 '15 at 20:25
  • The referenced question encompasses more than one operation, as do the answers – dwn Jan 05 '15 at 20:35
  • 1
    @dwn The accepted answer is the usual superstitious rubbish about `==` (equality operator which does not occur in this question) and doe snot explain why the floating-point result should be different from the expected one when **all the floating-point operations involved are exact**. – Pascal Cuoq Jan 05 '15 at 22:34
  • @PascalCuoq: The accepted answer is community wiki at this point. – tmyklebu Jan 06 '15 at 02:05

4 Answers4

7

This happens because 11.20 is not exactly 1120/100 but slightly less than that. So 11.20 - 11 ends up slightly less than 20/100 (*). Multiplied by 100, 11.20 - 11 produces a floating-point number slightly below 20, and since int(...) truncates (rounds towards zero), the result is 19.

For efficiency reasons, floating-point numbers are represented as fractions with a power of two as the denominator. So 1/2, 1/4, 1/16, … can be represented exactly as floating-point numbers, but 1/5 cannot (there is no power of two that can be used as the denominator to represent 1/5 exactly).

(*) This floating-point subtraction happens to be exact, so that the absolute error of the result compared to 20/100 is exactly the same as the absolute error of 11.20 compared to 1120/100. Note that the relative error is magnified, because the same absolute error is applied to a much smaller value. The subtraction of values that are already inexact and are close is called “catastrophic cancellation”, and the subtraction in your Python line is one such catastrophic cancellation.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
4
11.2 - 11

actually yields

0.1999999999999993

which rounds down to 19.

Adib Saad
  • 552
  • 3
  • 10
1

In Python int() truncates toward 0 for reasons Guido explains here. This means negative numbers will actually see the opposite effect (related SO question & answer).

Community
  • 1
  • 1
Tom
  • 22,301
  • 5
  • 63
  • 96
  • “flooring” means rounding towards -infinity. `int(…)` truncates, which means rounding towards 0. They are the same thing for positive numbers but not for negative numbers. – Pascal Cuoq Jan 05 '15 at 20:27
0

As said, it is a rounding issue with floating points precision. You can see that using :

print '%.20f' % (100*(11.20 - 11))
>>> 19.99999999999992894573
njzk2
  • 38,969
  • 7
  • 69
  • 107