Python Friday #202: Rounding in Python

Python is usually a straightforward language without surprises. However, when you use the round() function you may run into some strange behaviour. Let us have a look at the specialities of round() and what is going on.

This post is part of my journey to learn Python. You find the code for this post in my PythonFriday repository on GitHub.

 

Rounding numbers – as expected

We can use the round() function to round a number like 3.51 to 4. For that example, we write this code:

Since we omitted the second parameter of the round() function, the default value for ndigits is set so that we get an integer back.

If we run this little script, we get the rounded numbers that we expect:

round(3.4) is 3
round(3.5) is 4
round(3.51) is 4
round(4.51) is 5

So far, so good and without any surprises.

What do you expect if you run this code?

The result is 4, not 5. That is unexpected, right?

 

Rounding numbers – the surprise

I was surprised by the result of round(4.5) and made this little test script to see what is going on:

round(1.5) is 2
round(2.5) is 2
round(3.5) is 4
round(4.5) is 4
round(5.5) is 6
round(6.5) is 6
round(7.5) is 8
round(8.5) is 8
round(9.5) is 10

We can see that 1.5 is rounded up to 2, but 2.5 is rounded down to 2. 3.5 is rounded up to 4 while 4.5 is rounded down to 4. We can extend the script, but it will always produce the same behaviour: n.5 is rounded up if n is odd and rounded down if n is even – always giving us even numbers.

If we look at the documentation of round() we find this explanation in the middle of the paragraph:

if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2).

This behaviour is called Gaussian rounding or bankers’ rounding and has this benefit:

This function minimizes the expected error when summing over rounded figures, even when the inputs are mostly positive or mostly negative, provided they are neither mostly even nor mostly odd.

 

Conclusion

The result we get with round() may not be what we expect, but there is an explanation for the behaviour that makes sense. I hope this post help to you understand this specialty of Python. Should you need a different behaviour, then read this article from Real Python on rounding.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.