Java Money odd number division and rounding without losing/gaining cents

726 Views Asked by At

I have a rounding problem regards to money calculation and its precision.

I am using Java Money (Moneta) libaray for all my calculations.

I store BigDecimal values in database using NUMERIC(19,4)

Problem

Given I have shopping cart in total amount EUR 323.99. I want to offer paying by instalments for this cart for 3 months without interest rate.

When doing 323.99 / 3 you will get Money representation of EUR 108.00 (default rounding HALF_EVEN) and BigDecimal representation of 107.9966...667

Monthly payment is stored as 107.9967 numeric value inside database for all 3 equal payments.

On Invoice I would display EUR 108.00 monthly payment for customer.

When I recieve customer payment of EUR 108.00, I am trying to allocate this transaction amount to the outstanding payment, which is Money with internal number value of 107.9967. On my query side I would want to calculate and display the remaining principal balance for this order, but with these numbers I am unable to produce accurate fractional part as I am not allowed to do any manual rounding here or else I would lose precision.

For example if I would do following calculations over 3 payments:

1) 323.99 - 107.9967 = 215.9933
2) 215.9933 - 107.9967 = 107.9966
3) 107.9966 - 107.9967 = -0.0001

I am left with Money value of EUR 0.00 with internal BigDecimal value -0.0001

Same would happen when calculating another way aswell. Final result would be positive 0.0033 for example which is represented as EUR 0.00, but when when it is accumulated, then second time it would be 0.0066 which gets already rounded to EUR 0.01, as if customer would have gained 1 cent.

Question

Are there any suggestions how such calculations should be performed or truncated or excplicitly rounded?

How should I handle this kind of value? In reality I shouldn't care about any values past 2 decimal points when it is 0.00, but in a long run customer transaction log sum would start to accumulate cents out of these calculations. Is it OK to someway strip all values that come after 0.00 and leave it completely as real 0?

1

There are 1 best solutions below

0
On

If you use the modulus(amount, n) where n is the number of payments to get the remainder you can determine n-1 equal payments plus one special payment of of the equal payment plus the modulus(amount, n). This should work for all combination I believe.