views:

113

answers:

2

Take the following example:

>>> from decimal import Decimal
>>> nrml_price = Decimal('0.59')
>>> discounted = nrml_price / 3  # Taking 2/3 off the price with a coupon
Decimal('0.1966666666666666666666666667')  # Customers don't have fractions of a penny
>>> (nrml_price / 3).quantize(D('0.00'))  # So I quantize to get 2 decimal places
Decimal('0.20')  # Ca fait combien? Cest vingt cents.

The problem is that I've now technically charged the customer for more than the expected price, albeit by less than 3/10 of a cent, but nonetheless it is technically incorrect.

How do I overcome a problem like this? Do I ignore it as a fact of life, or is there an accepted way to do this sort of thing (e.g. always charge the customer the nearest penny down)?

+4  A: 

The answer here may actually depend more on your transaction processor. Does your transaction processor allow you to transfer amounts of currency that are not whole numbers of cents? What about irrational value currency amounts? Say the discount was the square root of the normal price?

Most vendors (thats you here) will simply round up and keep the difference, in whole cents.

TokenMacGuy
@Token - are you Russell K. M.?
orokusaki
+7  A: 

"is there an accepted way to do this sort of thing"

Yes. Accountants do it all the time.

Indeed COBOL does this really well.

The Python decimal package has a bunch of rounding options that you set in the context. Almost always the decimal.ROUND_HALF_DOWN or decimal.ROUND_HALF_EVEN options are what you want in your context.

When building software for retail management like this, there will be corporate policies in place, managed by real accountants, which specify what should be done.

Ask the accountant who works with this line of business what the policy is.

S.Lott
@orokusaki: When you ran that exact experiment, what did you learn?
S.Lott
@S.Lott - I didn't. That's why I asked you - I gave you 15 points toward your 100k goal man :)
orokusaki
@orokusaki: Please take the hint. Actually run the actual experiment. It's 4 lines of code and you'll learn more from running the experiment than from asking dozens of similar questions. There's actually less value to you if I run the experiment and post the results. Please actually write the actual experiment and actually run it. It's helpful to you. You will learn more from that than from any answer I could ever give.
S.Lott
@S.Lott - Thanks, it was really interesting. You know what came to mind; the question about the egg sitting on the point of a roof. There is exactly no fair way to decide whether to round down, or to round up. The most confusing part is the default `ROUND_HALF_EVEN` which rounds up. Why would they call it that? There is only `ROUND_HALF_UP` or `ROUND_HALF_DOWN` in reality, no?
orokusaki