# Compare monetary doubles

Tom Johnson
Ranch Hand
Posts: 142
Hi all,
I want to compare 2 values to two decimal places, basically monetary values. I know about precision issues with straight up double comparison using ==, so to check are two values equal (to 2 places) I do the following:

I'm not sure if the negative zero is overkill, but will is this approach safe and correct for monetary comparisons?

Thanks

Campbell Ritchie
Sheriff
Posts: 49361
62
I don't think you have any overkill there; the thing that bothers me is converting from double to BigDecimal. You ought to use BigDecimal throughout.

Tom Johnson
Ranch Hand
Posts: 142
Yep I realise that.....unfortunately part of the system is a legacy application which I cannot change and it uses doubles. What I am hoping to achieve is to use the rounding at the end of the use case to shave off the precision errors before my comparison. Is that achieveable?

Campbell Ritchie
Sheriff
Posts: 49361
62
Tom Johnson wrote:Yep I realise that.....unfortunately part of the system is a legacy application which I cannot change and it uses doubles. . . .
Yes, you have been dropped in it . . .

If you really get your value to 0, then 0 is exactly representable (I think) as a double, so you can use the == operator on two doubles. As an alternative you can use BigDecimal1.compareTo(BigDecimal2) == 0.

Tom Johnson
Ranch Hand
Posts: 142
Thanks Campbell!

That seems to work.....just wondering is it safe to use plain 0.005 or could that really be 0.0049999999999999994 or similar?

Which would you recommend? BigDecimal method I think looks a bit clearer, as you can see immediately i'm rounding to 2 deciaml places and then comparing. Your last solution is easier (code-wise) but I think you need to take a second look to see whats going on.....

This is so much more awkward than I feel it should be!

Any other thoughts welcome....

Campbell Ritchie
Sheriff
Posts: 49361
62
It depends . . .

If you have had that legacy system running and producing results for several years and nobody has noticed an error, you can probably get away with it.

If you have a double like 123456789.87 for £123456789.87 or \$123456789.87 or €123456789.87 etc, that is 11 figures. A double has a precision (as long as you are inside the normalised range, which you always ought to be for money) of 15-16 decimal places, so the errors in that sort of arithmetic are likely to be 4 decimal places smaller, ie starting with 0.00000. So if your 0.005 is really 0.00499999999999999999937563465346583912345, it will still be more than the likely error.

By the way: I tried it with Double.parseDouble and different BigDecimal constructors, and got this value for 0.05: 0.05000000000000000277555756156289135105907917022705078125

Anybody disagree with me? Please speak up if you think I am up the creek.

Tom Johnson
Ranch Hand
Posts: 142
Campbell Ritchie wrote:
By the way: I tried it with Double.parseDouble and different BigDecimal constructors, and got this value for 0.05: 0.05000000000000000277555756156289135105907917022705078125

Aarrrgggh!

I think im going to go with this the following. I think its clear whats going on and should work OK:

Again the compare to MINUS_ZERO is probably overkill but just in case there are some quirks to some JVM...!