Decimals to 2 places for money in Python 3

血红的双手。 提交于 2019-11-27 14:44:17

问题


How do I get my decimals to stay at 2 places for representing money using the decimal module?

I've setting the precision, and damn near everything else, and met with failure.


回答1:


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 * quantity
cents = decimal.Decimal('.01')
money = price.quantize(cents, decimal.ROUND_HALF_UP)



回答2:


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



回答3:


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.



回答4:


One way to solve this is to store money values in cents as integers, and only convert to decimal representation when printing values. This is called fixed point arithmetic.




回答5:


>>> decimal.getcontext().prec = 2
>>> d = decimal.Decimal('2.40')
>>> d/17
Decimal('0.14')

You just have to set the precision to 2 (the first line) and them everything will use no more than 2 decimal places

Just for comparison:

>>> 2.4 / 17
0.1411764705882353


来源:https://stackoverflow.com/questions/7560455/decimals-to-2-places-for-money-in-python-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!