0

Code:

numbers = (0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19)
for i in numbers:
    print i,"=> %.1f" % i

Output:

0.11 => 0.1
0.12 => 0.1
0.13 => 0.1
0.14 => 0.1
0.15 => 0.1
0.16 => 0.2
0.17 => 0.2
0.18 => 0.2
0.19 => 0.2

I expected either that it will simply truncate unwanted numbers or that it will round them, but I receive something indirect. It didn't truncate because we get 0.2 and it didn't round because for 0.15 returns 0.1 instead of the expected 0.2.

I don't see any sense in it. Can somebody tell me how does it REALLY works?

*I tried various cases and always for X.X...X5 i get X.XX instead of X.X...(X+1). From zero to five numbers are truncated, from six to nine they are rounded.

user3616181
  • 975
  • 2
  • 8
  • 27
  • 3
    `format(.15, '.53f')` -> `'0.14999999999999999444888487687421729788184165954589844'`. Floating point is an **approximation**, not a precise number. You cannot precisely represent 0.15 in a floating point value. – Martijn Pieters May 17 '14 at 08:53
  • Oh. For example for 8.75 (8.75000000000000000000000000000000000000000000000000000) it works as I expected (returns 8.8). Now I think I get it. This statement actually rounds numers but they representation in computer memory is a bit different so we sometimes get incorrect results. Am I right? – user3616181 May 17 '14 at 09:20
  • Indeed, 0.75 (3 quarters) can be precisely modelled by binary fractions (1/2 + 1/4). For 0.15, you need to add 1/8, 1/64, 1/1024, 1/2048, 1/16384, 1/32768, etc. and still not get quite there before you run out of bits to represent all those fractions. – Martijn Pieters May 17 '14 at 09:24
  • Is it a way to deal with it? It's only an academic problem but I try to print 0.2 from 0.15. I tried various ways: `num = 0.15` `print "%.1f" % num` `print round(num, 1)` `print '%.1f' % round(num, 1)` but I always get 0.1 as a result. Is it even possible or should I just give up? – user3616181 May 17 '14 at 09:33
  • Switch to [`decimal.Decimal()`](https://docs.python.org/2/library/decimal.html) if precision like this is more important than hardware-accelerated arithmetic. – Martijn Pieters May 17 '14 at 09:49
  • I think I don't get it, because for this code I get the same result `from decimal import * a = Decimal(0.15) print a print "%.1f" % a` – user3616181 May 17 '14 at 10:00
  • You *started* with a float. You gave `Decimal()` a value that is an approximation. Start with a string instead: `Decimal('0.15')`. Also, read the manual, you probably need to set the rounding mode. – Martijn Pieters May 17 '14 at 10:13

0 Answers0