Ошибка Python с плавающей точкой 117.285 раунд до 117.28 не 117.29

Я использую python 2.7, а код, который у меня есть:

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

и результат, который я ожидаю, составляет 117,29, но он показывает 117,28. Как решить проблему?

Ответ 1

Если Python использует 64-битный двоичный тип с плавающей точкой IEEE-754, то точное значение, которое он использует, будет

117.284999999999996589394868351519107818603515625

... и, очевидно, ниже средней точки между 117.28 и 117.29. Возможно, что то, что происходит.

Другой вариант заключается в том, что Python использует Rounding Banker.

Если для вас важны точные десятичные значения, вы можете вместо этого использовать decimal.

Ответ 2

г. Skeet имеет правильный ответ, ниже приведен пример того, как использовать decimal, на который он ссылается:

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')"

Ответ 3

Если вы хотите простое решение и не заботитесь о производительности, вы можете использовать такую ​​функцию, чтобы преобразовать в integer, round и 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)