Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python float round error 117.285 round to 117.28 not 117.29

Tags:

python

I am using python 2.7, and the code I have is:

a = 10.5 * 22.34 / 2.0
print "%.2f" % a

and the result I expect is 117.29, but it shows 117.28. How to solve the problem?

like image 909
Peiti Li Avatar asked Feb 15 '12 21:02

Peiti Li


3 Answers

If Python is using a 64-bit IEEE-754 binary floating point type, then the exact value it's using will be

117.284999999999996589394868351519107818603515625

... and that's obviously lower than the midpoint between 117.28 and 117.29. It's possible that that's what's going on.

Another option is that Python is using Banker's Rounding.

If the exact decimal values matter to you, you might want to consider using decimal instead.

like image 76
Jon Skeet Avatar answered Nov 14 '22 22:11

Jon Skeet


Mr. Skeet has the correct answer, below is an example of how to use the decimal module to which he refers:

import decimal
a = decimal.Decimal('117.285')
rounded = a.quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_HALF_UP)
print rounded
# 117.29
repr(rounded)
# "Decimal('117.29')"
like image 44
mechanical_meat Avatar answered Nov 14 '22 21:11

mechanical_meat


If you want a simple solution and don't care about performance, you could use a function like this to convert to integer, round, and convert back to float:

def round_exact(number, decimal_places=0):
    """Round the number to the given number of decimal places by converting to 
    and from integers to avoid floating point error."""
    factor = 10**(decimal_places + 1)
    rounded_int = int(number * factor)
    if rounded_int % 10 >= 5:
        # Round up
        return (int(rounded_int//10) + 1) / float(factor//10)
    # Round down
    return int(rounded_int//10) / float(factor//10)
like image 35
user1389840 Avatar answered Nov 14 '22 22:11

user1389840