Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python decimals - rounding to nearest whole dollar (no cents) - with ROUND_HALF_UP

I'm trying to use Decimal.quantize() to achieve the following: -

For any amount of money, expressed as a python decimal of default precision, I want to round it using decimal.ROUND_HALF_UP so that it has no cents after rounding.

For example, given 1.25, I'm trying to obtain 1.00 (signifying no cents)

given 1.49 I'm trying to obtain 1.00

given 1.50 I'm trying to obtain 2.00

given 1.87 I'm trying to obtain 2.00

given 2.00 I'm trying to obtain 2.00

So there are two ranges for the cents -- 0 cent to 49 cents; and 50 cents to 99 cents. For cents upto 49, I want to round down, for cents 50 and up I want to round up. I'm trying to obtain the result with two significant decimal places (which will always be 00).

I don't have any negative values to deal with here. How do I round my dollars to get the amount I want? Also is there any other option other than quantize?

like image 533
chefsmart Avatar asked Oct 14 '10 17:10

chefsmart


Video Answer


1 Answers

I'd try something like the following:

>>> from decimal import Decimal, ROUND_HALF_UP
>>> x = Decimal('2.47')
>>> x.quantize(Decimal('1'), rounding=ROUND_HALF_UP).quantize(Decimal('0.01'))
Decimal('2.00')

The key part here is the first call: x.quantize(Decimal('1'), rounding=ROUND_HALF_UP) gives x rounded to the nearest integer, with the given rounding mode. The first argument (Decimal('1')) determines the exponent of the rounded result, so if you replaced it with e.g., Decimal('0.1') it would round to the nearest tenth, instead, and if you replaced it with Decimal('1e1') it would round to the nearest multiple of 10.

Then the second quantize call just puts the extra two decimal places back in so that you get Decimal('2.00') coming out instead of just Decimal(2).

You could also use the to_integral_value method in place of the first quantize call, if you want:

>>> x.to_integral_value(rounding=ROUND_HALF_UP).quantize(Decimal('0.01'))
Decimal('2.00')

I can't see any strong reason to prefer either solution over the other.

like image 110
Mark Dickinson Avatar answered Sep 19 '22 20:09

Mark Dickinson