Why is Python's round so strange?
Take a look at the documentation:
Note The behavior of
round()
for floats can be surprising: for example,round(2.675, 2)
gives2.67
instead of the expected2.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 fraction2.675
is exactly halfway between2.67
and2.68
, you might expect the result here to be (a binary approximation to)2.68
. It’s not, because when the decimal string2.675
is converted to a binary floating-point number, it’s again replaced with a binary approximation, whose exact value is2.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')
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.