-2

why round(1.45, 1) gives 1.4 but when I try to round(2.45, 1) it gives 2.5 not 2.4

Adam.Er8
13.5k3 gold badges32 silver badges43 bronze badges
asked Jun 27, 2019 at 12:08
6
  • It's a representation error. Commented Jun 27, 2019 at 12:10
  • 1
    Hint: print('{0:.17f}'.format(1.45)) and print('{0:.17f}'.format(2.45)) See also Is floating point math broken? Commented Jun 27, 2019 at 12:15
  • 1
    @Georgy Not quite. That one is about banker's rounding, which isn't really the issue here. Commented Jun 27, 2019 at 12:21
  • @Georgy No, that's still banker's rounding. Commented Jun 27, 2019 at 12:31
  • There were lots of other similar questions asked before: stackoverflow.com/questions/linked/10825926?lq=1 Commented Jun 27, 2019 at 12:31

2 Answers 2

3

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.

answered Jun 27, 2019 at 12:20
Sign up to request clarification or add additional context in comments.

2 Comments

Actually in math most people get taught to round to the next even number if you are rounding at 0.5. So 1.5 and 2.5 both round to 2. This is because the .5 is exactly in the middle so with transactions where the total came to $xx.xy5 rounding would depend on the value of y giving a ~50/50 / fair chance to round up or down the last penny.
You can read Bankers Rounding for a more complete explanation
1

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

answered Jun 27, 2019 at 12:19

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.