| Author |
Compare monetary doubles
|
Tom Johnson
Ranch Hand
Joined: May 11, 2005
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
|
<a href="http://faq.javaranch.com/java/UseCodeTags" target="_blank" rel="nofollow">Use Code Tags!!</a>
|
 |
Campbell Ritchie
Sheriff
Joined: Oct 13, 2005
Posts: 32694
|
|
|
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
Joined: May 11, 2005
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
Joined: Oct 13, 2005
Posts: 32694
|
|
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.
But there might be a simpler solution. How about this?Anybody else??
|
 |
Tom Johnson
Ranch Hand
Joined: May 11, 2005
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
Joined: Oct 13, 2005
Posts: 32694
|
|
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
Joined: May 11, 2005
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...!
|
 |
 |
|
|
subject: Compare monetary doubles
|
|
|