Reputation: 1604
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.
Upvotes: 29
Views: 28723
Reputation: 2769
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)
Upvotes: 54
Reputation: 1990
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
Upvotes: 23
Reputation: 1091
Falsehoods programmers believe about money:
Upvotes: 26
Reputation: 33397
>>> 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
Upvotes: 0
Reputation: 993273
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.
Upvotes: 2