I have the following code in Java;
BigDecimal price; // assigned elsewhere
if (price.compareTo(new BigDecimal("0.00")) == 0) {
return true;
}
What is the best way to write the if condition?
I have the following code in Java;
BigDecimal price; // assigned elsewhere
if (price.compareTo(new BigDecimal("0.00")) == 0) {
return true;
}
What is the best way to write the if condition?
Use compareTo(BigDecimal.ZERO)
instead of equals()
:
if (price.compareTo(BigDecimal.ZERO) == 0) // see below
Comparing with the BigDecimal
constant BigDecimal.ZERO
avoids having to construct a new BigDecimal(0)
every execution.
FYI, BigDecimal
also has constants BigDecimal.ONE
and BigDecimal.TEN
for your convenience.
The reason you can't use BigDecimal#equals()
is that it takes scale into consideration:
new BigDecimal("0").equals(BigDecimal.ZERO) // true
new BigDecimal("0.00").equals(BigDecimal.ZERO) // false!
so it's unsuitable for a purely numeric comparison. However, BigDecimal.compareTo()
doesn't consider scale when comparing:
new BigDecimal("0").compareTo(BigDecimal.ZERO) == 0 // true
new BigDecimal("0.00").compareTo(BigDecimal.ZERO) == 0 // true
Alternatively, signum() can be used:
if (price.signum() == 0) {
return true;
}
There is a constant that you can check against:
someBigDecimal.compareTo(BigDecimal.ZERO) == 0
Alternatively, I think it is worth mentioning that the behavior of equals and compareTo methods in the class BigDecimal are not consistent with each other.
This basically means that:
BigDecimal someValue = new BigDecimal("0.00");
System.out.println(someValue.compareTo(BigDecimal.ZERO) == 0); // true
System.out.println(someValue.equals(BigDecimal.ZERO)); // false
Therefore, you have to be very careful with the scale in your someValue
variable, otherwise you would get unexpected results.
I usually use the following:
if (selectPrice.compareTo(BigDecimal.ZERO) == 0) { ... }
You would want to use equals()
since they are objects, and utilize the built in ZERO
instance:
if (selectPrice.equals(BigDecimal.ZERO))
Note that .equals()
takes scale into account, so unless selectPrice is the same scale (0) as .ZERO
then this will return false.
To take scale out of the equation as it were:
if (selectPrice.compareTo(BigDecimal.ZERO) == 0)
I should note that for certain mathematical situations, 0.00 != 0
, which is why I imagine .equals()
takes the scale into account. 0.00
gives precision to the hundredths place, whereas 0
is not that precise. Depending on the situation you may want to stick with .equals()
.
A simple and better way for your exemple is:
BigDecimal price;
if(BigDecimal.ZERO.compareTo(price) == 0){
//Returns TRUE
}
GriffeyDog is definitely correct:
Code:
BigDecimal myBigDecimal = new BigDecimal("00000000.000000");
System.out.println("bestPriceBigDecimal=" + myBigDecimal);
System.out.println("BigDecimal.valueOf(0.000000)=" + BigDecimal.valueOf(0.000000));
System.out.println(" equals=" + myBigDecimal.equals(BigDecimal.ZERO));
System.out.println("compare=" + (0 == myBigDecimal.compareTo(BigDecimal.ZERO)));
Results:
myBigDecimal=0.000000
BigDecimal.valueOf(0.000000)=0.0
equals=false
compare=true
While I understand the advantages of the BigDecimal compare, I would not consider it an intuitive construct (like the ==, <, >, <=, >= operators are). When you are holding a million things (ok, seven things) in your head, then anything you can reduce your cognitive load is a good thing. So I built some useful convenience functions:
public static boolean equalsZero(BigDecimal x) {
return (0 == x.compareTo(BigDecimal.ZERO));
}
public static boolean equals(BigDecimal x, BigDecimal y) {
return (0 == x.compareTo(y));
}
public static boolean lessThan(BigDecimal x, BigDecimal y) {
return (-1 == x.compareTo(y));
}
public static boolean lessThanOrEquals(BigDecimal x, BigDecimal y) {
return (x.compareTo(y) <= 0);
}
public static boolean greaterThan(BigDecimal x, BigDecimal y) {
return (1 == x.compareTo(y));
}
public static boolean greaterThanOrEquals(BigDecimal x, BigDecimal y) {
return (x.compareTo(y) >= 0);
}
Here is how to use them:
System.out.println("Starting main Utils");
BigDecimal bigDecimal0 = new BigDecimal(00000.00);
BigDecimal bigDecimal2 = new BigDecimal(2);
BigDecimal bigDecimal4 = new BigDecimal(4);
BigDecimal bigDecimal20 = new BigDecimal(2.000);
System.out.println("Positive cases:");
System.out.println("bigDecimal0=" + bigDecimal0 + " == zero is " + Utils.equalsZero(bigDecimal0));
System.out.println("bigDecimal2=" + bigDecimal2 + " < bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThan(bigDecimal2, bigDecimal4));
System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal20=" + bigDecimal20 + " is " + Utils.equals(bigDecimal2, bigDecimal20));
System.out.println("bigDecimal2=" + bigDecimal2 + " <= bigDecimal4=" + bigDecimal4 + " is " + Utils.lessThanOrEquals(bigDecimal2, bigDecimal4));
System.out.println("bigDecimal4=" + bigDecimal4 + " > bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThan(bigDecimal4, bigDecimal2));
System.out.println("bigDecimal4=" + bigDecimal4 + " >= bigDecimal2=" + bigDecimal2 + " is " + Utils.greaterThanOrEquals(bigDecimal4, bigDecimal2));
System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal20=" + bigDecimal20 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal20));
System.out.println("Negative cases:");
System.out.println("bigDecimal2=" + bigDecimal2 + " == zero is " + Utils.equalsZero(bigDecimal2));
System.out.println("bigDecimal2=" + bigDecimal2 + " == bigDecimal4=" + bigDecimal4 + " is " + Utils.equals(bigDecimal2, bigDecimal4));
System.out.println("bigDecimal4=" + bigDecimal4 + " < bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThan(bigDecimal4, bigDecimal2));
System.out.println("bigDecimal4=" + bigDecimal4 + " <= bigDecimal2=" + bigDecimal2 + " is " + Utils.lessThanOrEquals(bigDecimal4, bigDecimal2));
System.out.println("bigDecimal2=" + bigDecimal2 + " > bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThan(bigDecimal2, bigDecimal4));
System.out.println("bigDecimal2=" + bigDecimal2 + " >= bigDecimal4=" + bigDecimal4 + " is " + Utils.greaterThanOrEquals(bigDecimal2, bigDecimal4));
The results look like this:
Positive cases:
bigDecimal0=0 == zero is true
bigDecimal2=2 < bigDecimal4=4 is true
bigDecimal2=2 == bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal20=2 is true
bigDecimal2=2 <= bigDecimal4=4 is true
bigDecimal4=4 > bigDecimal2=2 is true
bigDecimal4=4 >= bigDecimal2=2 is true
bigDecimal2=2 >= bigDecimal20=2 is true
Negative cases:
bigDecimal2=2 == zero is false
bigDecimal2=2 == bigDecimal4=4 is false
bigDecimal4=4 < bigDecimal2=2 is false
bigDecimal4=4 <= bigDecimal2=2 is false
bigDecimal2=2 > bigDecimal4=4 is false
bigDecimal2=2 >= bigDecimal4=4 is false
Just want to share here some helpful extensions for kotlin
fun BigDecimal.isZero() = compareTo(BigDecimal.ZERO) == 0
fun BigDecimal.isOne() = compareTo(BigDecimal.ONE) == 0
fun BigDecimal.isTen() = compareTo(BigDecimal.TEN) == 0
We can use java.math.BigDecimal.signum()
Returns the signum function of this BigDecimal.
Returns:-1, 0, or 1 as the value of this BigDecimalis negative, zero, or positive.
BigDecimal price; // assigned elsewhere
if (price.signum() == 0) {
return true;
}
BigDecimal.ZERO.setScale(2).equals(new BigDecimal("0.00"));
There is a static constant that represents 0:
BigDecimal.ZERO.equals(selectPrice)
You should do this instead of:
selectPrice.equals(BigDecimal.ZERO)
in order to avoid the case where selectPrice
is null
.