To round a number in Python you can use the round()
function. It’s straightforward, but there is a nuance to be aware of. When you pass a number that is exactly halfway between two integers to this function, its behavior might be surprising:
1
2
3
4
5
round(1.5)
# 2
round(2.5)
# 2
This happens because round()
employs an algorithm known as bankers’ rounding (BR), instead of arithmetic rounding (AR). The key distinction between these algorithms is that for numbers of the form x + 0.5
, where x
is even, BR rounds the number down, not up, as it would be with AR.
The reasony why to use bankers’ rounding
When you want to round a single number, using BR algorithm might seem to have no sense, because it appears indeterministic. However, BR becomes advantageous for rounding a large set of numbers due to its statistical benefits. Consider the following set of measurements:
1, 3, 2.5, 5.5, 6.5, 4, 1.5, 8
Summing them up and calculating the average yields 32/8 = 4.
If we round each value using (AR) before calculating the average, the result changes to 34/8 = 4.25.
There is no objective reason why a number ending in .5 should always be rounded up. Statistically, such numbers should be rounded up and down with 50% probability. BR algorithm ensures this.
Available workarounds
One of the workarounds to achieve AR in Python is using int(x+0.5)
instead of round(x)
. This method is straightforward, but the formula becomes more complex when you want to round the number to n digits. For instance, to imitate round(x, n)
, the formula is:
int(x + 10**n + 0.5) / 10**n
Another workaround requires using decimal
library:
1
2
3
4
5
6
from decimal import Decimal
x = 1.556
precision = Decimal('0.00')
float(Decimal(x).quantize(precision))
# 1.56