Как мне получить десятичные числа, чтобы остаться в 2 местах для представления денег с помощью модуля decimal
?
Я устанавливаю точность и проклинаю почти все остальное, и встречался с ошибкой.
Как мне получить десятичные числа, чтобы остаться в 2 местах для представления денег с помощью модуля decimal
?
Я устанавливаю точность и проклинаю почти все остальное, и встречался с ошибкой.
При работе с деньгами вы обычно хотите ограничить точность как можно позже, чтобы такие вещи, как умножение, не суммировали ошибки округления. В python 2 и 3 вы можете .quantize()
a Decimal
выполнить любую требуемую точность:
unit_price = decimal.Decimal('8.0107')
quantity = decimal.Decimal('0.056')
price = unit_price * quantity
cents = decimal.Decimal('.01')
money = price.quantize(cents, decimal.ROUND_HALF_UP)
Принятый ответ в основном правильный, за исключением константы, используемой для операции округления. Вы должны использовать ROUND_HALF_UP
вместо ROUND_05UP
для валютных операций. Согласно docs:
десятичное. ROUND_HALF_UP
Круглый к ближайшему с увязками, уходящими от нуля.
десятичное. ROUND_05UP
округление от нуля, если последняя цифра после округления к нулю равна 0 или 5; в противном случае округляется к нулю.
Использование ROUND_05UP
будет только округлять (для положительных чисел), если число в сотых местах было равным 5 или 0, что неверно для математической математики.
Вот несколько примеров:
>>> from decimal import Decimal, ROUND_05UP, ROUND_HALF_UP
>>> cents = Decimal('0.01')
>>> Decimal('1.995').quantize(cents, ROUND_HALF_UP)
Decimal('2.00') # Correct
>>> Decimal('1.995').quantize(cents, ROUND_05UP)
Decimal('1.99') # Incorrect
>>> Decimal('1.001').quantize(cents, ROUND_HALF_UP)
Decimal('1.00') # Correct
>>> Decimal('1.001').quantize(cents, ROUND_05UP)
Decimal('1.01') # Incorrect
Программисты лживости верят в деньги:
Один из способов решения этой проблемы - хранить денежные значения в центах как целые числа и преобразовывать их только в десятичное представление при печати значений. Это называется арифметикой с фиксированной точкой.
>>> decimal.getcontext().prec = 2
>>> d = decimal.Decimal('2.40')
>>> d/17
Decimal('0.14')
Вам просто нужно установить точность на 2 (первая строка), и все они будут использовать не более двух знаков после запятой
Просто для сравнения:
>>> 2.4 / 17
0.1411764705882353