11

My code:

  #!/usr/bin/python
  # -*- coding: utf-8 -*-
  print (round(1.555, 1))  # It seems normal
  print (round(1.555, 2))  # Why it is not output 1.56?
  print (round(1.556, 2))  # It seems normal

Output:

  sam@sam:~/code/python$ ./t2.py
  1.6
  1.55
  1.56
  sam@sam:~/code/python$

round(1.555, 1) outputs 1.6.

Why doesn't round(1.555, 2) output 1.56?

ShadowRanger
  • 108,619
  • 9
  • 124
  • 184
sam
  • 1,683
  • 3
  • 17
  • 25
  • look here: http://stackoverflow.com/questions/56820/round-in-python-doesnt-seem-to-be-rounding-properly – Robin Manoli Jan 10 '13 at 02:38
  • In floating point arithmetic in any programming language, you never want to rely on the assumption that a number is **exactly** anything. For the same reason, you should never ask `if x == 2.0`. This is the most important thing to know about floating point arithmetic. – cxrodgers Jan 10 '13 at 10:17

3 Answers3

15

Take a look at the documentation:

Note The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

If you keep digging (i.e. click that link), you'll find an example similar to yours:

The documentation for the built-in round() function says that it rounds to the nearest value, rounding ties away from zero. Since the decimal fraction 2.675 is exactly halfway between 2.67 and 2.68, you might expect the result here to be (a binary approximation to) 2.68. It’s not, because when the decimal string 2.675 is converted to a binary floating-point number, it’s again replaced with a binary approximation, whose exact value is

2.67499999999999982236431605997495353221893310546875

String formatting won't fix your problem either. The floating point number just isn't stored the way you'd expect it to be:

>>> '{:0.2f}'.format(1.555)
'1.55'

This isn't really a "fix", but Python does have a decimal module, which is designed for floating point arithmetic:

>>> from decimal import Decimal
>>> n = Decimal('1.555')
>>> round(n, 2)
Decimal('1.56')
Blender
  • 257,973
  • 46
  • 399
  • 459
6

Straight from the documentation:

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Hunter McMillen
  • 52,839
  • 21
  • 105
  • 154
  • in other words, when you write 1.555, python might actually be seeing something like 1.554999999999999999999999 and thus the rounding can get weird. – RodericDay Jan 10 '13 at 02:43
0

From http://docs.python.org/2/library/functions.html#round:

Note

The behavior of round() for floats can be surprising: for example, round(2.675, 2) gives 2.67 instead of the expected 2.68. This is not a bug: it’s a result of the fact that most decimal fractions can’t be represented exactly as a float. See Floating Point Arithmetic: Issues and Limitations for more information.

Adrián
  • 5,817
  • 1
  • 25
  • 46