why round(1.45, 1) gives 1.4 but when I try to round(2.45, 1) it gives 2.5 not 2.4
2 Answers 2
The reason is how floating points are stored internally. A float is rounded to its next valid value, according to IEEE 754.
print("{:.30f}".format(1.45))
print("{:.30f}".format(2.45))
1.449999999999999955591079014994
2.450000000000000177635683940025
Why those values are then rounded to 1.4 and 2.5 should be obvious.
The biggest issue here is how humans think vs how computers calculate: Humans think in base 10, computers in base 2. In base 2, 1.45 is a number with infinite digits, and therefore will be rounded.
If you want to force the computer to think in base 10, you can use the Decimal library:
from decimal import Decimal
print("{:.30f}".format(Decimal('1.45')))
print("{:.30f}".format(Decimal('2.45')))
print(round(Decimal('1.45'),1))
print(round(Decimal('2.45'),1))
1.450000000000000000000000000000
2.450000000000000000000000000000
1.4
2.4
This still might not be what you want, as in math we get taught that rounding 1.45 would result in 1.5. You can change the rounding behaviour in decimal like this:
import decimal
decimal.getcontext().rounding = decimal.ROUND_HALF_UP
1.450000000000000000000000000000
2.450000000000000000000000000000
1.5
2.5
Keep in mind, however, that the computer can calculate a lot faster in base 2 than in base 10.
2 Comments
you can use decimal module, as it proclaims:
The decimal module provides support for fast correctly-rounded decimal floating point arithmetic.
try this:
from decimal import Decimal
n1_45 = Decimal('1.45')
n2_45 = Decimal('2.45')
print(round(n1_45, 1), round(n2_45, 1))
Output:
1.4 2.4
print('{0:.17f}'.format(1.45))andprint('{0:.17f}'.format(2.45))See also Is floating point math broken?