I want to round the number below to two decimal places. The result must be 33.39 but Python gives 33.38 because the 5 rounds to even and hence to 8.
round(33.385, 2)
I want to round the number below to two decimal places. The result must be 33.39 but Python gives 33.38 because the 5 rounds to even and hence to 8.
round(33.385, 2)
This actually has nothing to do with round-to-nearest/even. 33.385 is a decimal number, but is represented in your hardware as an approximation in binary floating point. The decimal
module can show you the exact decimal value of that binary approximation:
>>> import decimal
>>> decimal.Decimal(33.385)
Decimal('33.38499999999999801048033987171947956085205078125')
That's why it rounds to 33.38: the exact value stored is slightly closer to 33.38 than to 33.39.
If you need exact decimal results, don't use your hardware's binary floating point. For example, you could use the decimal
module for this with the ROUND_HALF_UP
rounding mode.
For example,
>>> from decimal import Decimal as D
>>> x = D("33.385")
>>> x
Decimal('33.385')
>>> twodigits = D("0.01")
>>> x.quantize(twodigits) # nearest/even is the default
Decimal('33.38')
>>> x.quantize(twodigits, rounding=decimal.ROUND_HALF_EVEN) # same thing
Decimal('33.38')
>>> x.quantize(twodigits, rounding=decimal.ROUND_HALF_UP) # what you want
Decimal('33.39')
>>> float(_) # back to binary float
33.39
>>> D(_) # but what the binary 33.39 _really_ is
Decimal('33.3900000000000005684341886080801486968994140625')
Actually round()
rounds to the closest decimal point you specified. There are some incosistencies with floating point numbers in programming languages, because the computer can't create specific enough decimals with the given bits, so the programming language already shows you what you need to see, but not the real number. You can see the real number by using the decimal
library. That way you can see why sometimes numbers that end in 5 round either up or down.
If you want to round down then you can use the math
module to do it easily.
import math
math.floor(33.385 * 100) / 100
And if you want to round up then you can do the same with math.ceil
import math
math.ceil(33.385 * 100) / 100
Or if you wanted you could still use the round()
function, but change it a bit
Round up:
decimal_point = 2
change = 0.3 / 10**decimal_point
round(33.385 + change, decimal_point)
Round down:
decimal_point = 2
change = 0.3 / 10**decimal_point
round(33.385 - change, decimal_point)
You can do the following:
import math
math.ceil(33.385 * 100.0) / 100.0
Reference: Round up to Second Decimal Place in Python
Just a result of floating-point approximation by computers. Computers understand binary and not all floating point values have accurate binary rep. A famous example:
print(0.1 + 0.2 == 0.3)
False
Wonder why?
The result is 0.30000000000000004 and it's because 0.2 in binary goes as in 0.00110011001100...
Use @Rfroes87's suggestion to convert your numbers into an integer-precision scale and then round off to nearest integer)