Win a copy of Mesos in Action this week in the Cloud/Virtualizaton forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Compare monetary doubles

 
Tom Johnson
Ranch Hand
Posts: 142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 48950
60
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 48950
60
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Posts: 142
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
Pie
Posts: 48950
60
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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...!
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic