Decimals to 2 places for money in Python 3 Decimals to 2 places for money in Python 3 python python

Decimals to 2 places for money in Python 3


When working with money you usually want to limit precision as late as possible so things like multiplication don't aggregate rounding errors. In python 2 and 3 you can .quantize() a Decimal to any precision you want:

unit_price = decimal.Decimal('8.0107')quantity = decimal.Decimal('0.056')price = unit_price * quantitycents = decimal.Decimal('.01')money = price.quantize(cents, decimal.ROUND_HALF_UP)


The accepted answer is mostly correct, except for the constant to use for the rounding operation. You should use ROUND_HALF_UP instead of ROUND_05UP for currency operations. According to the docs:

decimal.ROUND_HALF_UP

    Round to nearest with ties going away from zero.

decimal.ROUND_05UP

    Round away from zero if last digit after rounding towards zero would have been 0 or 5; otherwise round towards zero.

Using ROUND_05UP would only round up (for positive numbers) if the number in the hundredths place was a 5 or 0, which isn't correct for currency math.

Here are some examples:

>>> 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


Falsehoods programmers believe about money:

  • Monetary values can be stored or represented as a floating point.
  • All currencies have a decimal precision of 2.
  • All ISO 4217 defined currencies have a decimal precision.
  • All currencies are defined in ISO 4217.
  • Gold is not a currency.
  • My system will never have to handle obscure currencies with more than 2 decimal places.
  • Floating point values are OK if the monetary value of transactions is "small".
  • A system will always handle the same currency (therefore we do not persist the currency, only the monetary value).
  • Storing monetary values as signed long integers will make them easier to work with, just multiply them by 100 after all arithmetic is done.
  • Customers will never complain about my rounding methods.
  • When I convert my application from language X to language Y, I don't have to verify if the rounding behavior is the same.
  • On exchanging currency A for currency B, the exchange rate becomes irrelevant after the transaction.