How does Rounding in Python work?
Asked Answered
D

3

5

I am a bit confused about how rounding in Python works.
Could someone please explain why Python behaves like this?

Example:

>>> round(0.05,1) # this makes sense
0.1
>>> round(0.15,1) # this doesn't make sense! Why is the result not 0.2?
0.1

And same for:

>>> round(0.25,1) # this makes sense
0.3
>>> round(0.35,1) # in my opinion, should be 0.4 but evaluates to 0.3
0.3

Edit: So in general, there is a possibility that Python rounds down instead of rounding up. So am I to understand that the only "abnormal" thing that can happen is that Python rounds down? Or may it also get rounded up "abnormally" due to how it is stored? (I haven't found a case where Python rounded up when I expected it to round down)

Drawstring answered 5/1, 2016 at 20:27 Comment(5)
Related: print '%.20f %.20f %.20f'%(.15, .25, .35)Principle
@Rob_phi: Not related: your subscript phi is rendered correctly even in the URL display in my address bar [when I click your username]...HOW?!?Malvin
@Malvin If you copy the URL to a text editor it will show up as http://stackoverflow.com/users/8747/rob%E1%B5%A9 - some browsers such as Chrome render the escaped unicode characters in the URL bar.Killoran
@Galax: cool, thanks!Malvin
Python 2 or Python 3? Note that the halfway case behaviour is different (for actual, honest-to-god halfway cases). For example, in Python 2, round(1.25, 1) will give 1.3, while in Python 3 it gives 1.2.Hic
H
12

This is actually by design. From Pythons' 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.

Hydranth answered 5/1, 2016 at 20:32 Comment(2)
Yep, in particular "0.15" is internally represented as 0.1499999999999999944488848768742172978818416595458984375, and "0.35" is 0.34999999999999997779553950749686919152736663818359375. Both of which reasonably round down.Witchery
So in general, there is a possibility that it gets rounded down instead of rounded up. So the only "abnormal" thing that can happen is that it gets rounded down? Or may it also get rounded up "abnormally" due to how it is stored? (I haven't found a case where it gets rounded up when I expect it to get rounded down.)Drawstring
K
8

It sounds to me like you need the decimal module:

from decimal import *
x = Decimal('0.15')
print x.quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)

Output:

0.2
Killoran answered 5/1, 2016 at 20:49 Comment(1)
@JonasKaufmann: If you need exact decimal representations, which it sounds like you do, this is the right answer. Also, this is why Cobol was invented. And. Still. In. Use. :(Malvin
M
4

As an example, here is a case where you get rounding up:

>>> round(0.0499999999999999999,1)
0.1

In this case, 17 "9"s are the minimum number to cause this behavior. This is because the internal representation of 0.0499999999999999999 is 0.05000000000000000277555756156289135105907917022705078125.

Malvin answered 5/1, 2016 at 20:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.