Reputation: 12373
The Java way to compare two BigDecimals is to use the compareTo() method, and check if the result is -1, 0 or 1.
BigDecimal a = new BigDecimal("1.23")
BigDecimal b = new BigDecimal("3.45")
if (a.compareTo(b) > 0)) { }
I have seen that some people are using this format in grails:
if (a > b) { }
Does this work correctly? I.e. will it get the decimals correct, or is it converting to float or similar and comparing that?
How about using "==" vs using equals()?
What is the consequence of something like this:
BigDecimal a = new BigDecimal("1.00")
BigDecimal b = new BigDecimal("1")
assert (a==b)
It seems to work, but we have had it so engrained in Java not to do this kind of thing.
How about +=? e.g.
a+=b?
Would this be the same as
a = a.add(b)
Where does one find this kind of thing out? I have two groovy books, and unfortunately neither mention BigDecimal comparison or arithmetic, only the conversion/declaration.
Upvotes: 5
Views: 5125
Reputation: 22303
The short answer is yes, it's safe to use ==
for BigDecimal
comparison in Groovy.
From the Groovy documentation Behaviour of == section:
In Java
==
means equality of primitive types or identity for objects. In Groovy==
translates toa.compareTo(b)==0
, if they areComparable
, anda.equals(b)
otherwise. To check for identity, there isis
. E.g.a.is(b)
.
Upvotes: 1
Reputation: 96424
Groovy allows overloading of operators. When a type implements certain methods then you can use a corresponding operator on that type.
For +
the method to implement is plus, not add.
For greater than or less than comparisons, Groovy looks for a compareTo method on the object, and for ==
it looks for a method named equals. (If you want to compare references as if using ==
in Java, you have to use is
.)
Here's a table of common math operators and the method used to overload them:
Operator Method
a + b a.plus(b)
a - b a.minus(b)
a * b a.multiply(b)
a / b a.divide(b)
a++ or ++a a.next()
a-- or --a a.previous()
a << b a.leftShift(b)
You can see that BigDecimal overloads some of these methods (you get operator overloading for plus, minus, multiply, and divide, but not for next, previous, or leftShift):
groovy:000> BigDecimal.methods*.name
===> [equals, hashCode, toString, intValue, longValue, floatValue, doubleValue,
byteValue, shortValue, add, add, subtract, subtract, multiply, multiply, divide,
divide, divide, divide, divide, divide, remainder, remainder, divideAndRemainde
r, divideAndRemainder, divideToIntegralValue, divideToIntegralValue, abs, abs, m
ax, min, negate, negate, plus, plus, byteValueExact, shortValueExact, intValueEx
act, longValueExact, toBigIntegerExact, toBigInteger, compareTo, precision, scal
e, signum, ulp, unscaledValue, pow, pow, movePointLeft, movePointRight, scaleByP
owerOfTen, setScale, setScale, setScale, stripTrailingZeros, toEngineeringString
, toPlainString, round, compareTo, getClass, notify, notifyAll, wait, wait, wait
, valueOf, valueOf, valueOf]
You get ==
, >
, <
, >=
, and <=
based on how your object implements equals and compareTo.
So the operator is causing methods declared already in BigDecimal, or added to BigDecimal by groovy, to get called. It is definitely not doing any kind of conversion to a primitive type like float in order to be able to use the operators on primitives.
The table is taken from this developerworks article by Andrew Glover and Scott Davis, which has more details and includes example code.
Upvotes: 2
Reputation: 2377
Groovy does a wonderful job of managing numbers and to infinite precision. First thing you should know is that any number that has a dot in it is by default a BigDecimal -- the reason for the infinite precision. Here is an example of what this means exactly. Consider this snippet:
System.out.println(2.0 - 1.1);
System.out.println(new BigDecimal(2.0).subtract(new BigDecimal(1.1)));
System.out.println(new BigDecimal("2.0").subtract(new BigDecimal("1.1")));
// the above will give these:
0.8999999999999999
0.899999999999999911182158029987476766109466552734375
0.9
This shows the endurance we have to go through to get something decent in Java. In Groovy, this is all you have to do:
println 2 - 1.1
to get your 0.9! Try this on the Groovy web console. Here, the second operand is a BigDecimal, so the entire calculation is in BigDecimal, and precision is what Groovy would strive for to finish off clean in this case.
But how? This is because almost every operator in Groovy is mapped onto method calls on objects under the hood, so a + b is a.plus(b), and a==b translates to a.compareTo(b). It is therefore safe to assume what you assumed and this is the Groovy way of doing things: write less, expressively, and Groovy will do the work for you. You can learn about all this in the Groovy-lang documentation page with examples all over.
Upvotes: 1