Equals operator for zeros (BigDecimal / Double) in Java - java

A few interesting observations w.r.t equals operator on 0 and 0.0
new Double(0.0).equals(0) returns false, while new Double(0.0).equals(0.0) returns true.
BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0)) returns false, while BigDecimal.ZERO.equals(BigDecimal.valueOf(0)) returns true.
Looks like the string comparison is being done in both the cases. Could anyone throw some light on this.
Thanks.

BigDecimal 'equals' compares the value and the scale. If you only want to compare values (0 == 0.0) you should use compareTo:
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0 //true
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0 //true
See the javadoc.
As for the Double comparison, as explained by other answers, you are comparing a Double with an Integer in new Double(0.0).equals(0), which returns false because the objects have different types. For reference, the code for the equals method in JDK 7 is:
public boolean equals(Object obj) {
return (obj instanceof Double)
&& (doubleToLongBits(((Double)obj).value) ==
doubleToLongBits(value));
}
In your case, (obj instanceof Double) is false.

The 0 in your first expression is interpreted as an int, which may be autoboxed into an Integer, but not to a Double. So the type of the two is different, hence they are not equal. OTOH 0.0 is a double, which is autoboxed into a Double, so the two operands are deemed equal.
BigDecimals also contain a scale (i.e. number of digits to the right of the decimal separator dot). BigDecimal.ZERO has the value of "0", so its scale is 0. Hence it is not equal to "0.0", whose scale is 1.
If you want to compare values, use BigDecimal.compareTo:
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0.0)) == 0
BigDecimal.ZERO.compareTo(BigDecimal.valueOf(0)) == 0

new Double(0.0).equals(0) is actually boxed as something like this:
new Double(0.0).equals(Integer.valueOf(0))
Double.equals(...) will never return true unless given another Double instance.

new Double(0.0).equals(0); //false
as the argument you passed is integer. and the equels() in Double class checks whether the argument is od instance Double or not using instance of operator.
The Double's equals() method.
if (!(argument instanceof Double))
return false;
The argument you passed is integer, which is not instance of Double, so it returns false.

new Double(0.0).equals(0)
This line compares a double value of 0 (which is not exact zero) with integer of 0.
BigDecimal.ZERO.equals(BigDecimal.valueOf(0.0))
BigDecimal will compare the scale length in the equals operation.

For performance considerations BigDecimal, BigInteger caches small values
0 to 15 in case of BigDecimal (without fractions)
BigDecimal.ZERO will be new BigDecimal(BigInteger.ZERO, 0, 0, 1)
& valueOf method typically picks up from cache for 0 to 15 :)

please try doublevalue instead of compareto if you feel is not as beautiful and readable as or simply need an alternative like below:
BigDecimal a = new BigDecimal("0.00");
BigDecimal b = new BigDecimal("0.0");
BigDecimal c = new BigDecimal("0");
if(a.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("a equals");
}
if(b.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("b equals");
}
if(c.doubleValue()==BigDecimal.ZERO.doubleValue()) {
System.out.println("c equals");
}

Related

compare -999 in type double in Java with == and .equals()

Edit: Some people stated that this is possible duplicate of one of question asking how to compare string values. I was asking about comparing double with int, that is why .equal() did not work.
First, I set a LinkedList of doubles with first element = -999
then if the comparison is
return listOfNumber.getFirst().equals(-999);
the outcome will be false.
However if the comparison is written as
return listOfNumber.getFirst()== -999;
Then the outcome will be true.
I thought .equals() compares the value and == compare the object and == can only take -128 to 127. So why exactly I cannot use .equals to compare doubles?
Also if the LinkedList is String with first element = "a"
if I use
return ListOfString.getFirst() == "a";
then the outcome is false
but if I use
return ListOfString.getFirst().equals("a");
then the outcome is true.
I am very confused why the comparison of double and string need to be different to yield correct result?
Your problem is caused by autoboxing in Java.
Assuming (as you stated listOfNumber is a list of Double`):
ArrayList<Double> listOfNumber = new ArrayList<>();
listOfNumber.add(-999);
Since Java knows the signature of ... add(T) is ... add(Double), your add statement gets translated to:
listOfNumber.add(Double.valueOf(-999));
When you are executing
return listOfNumber.getFirst().equals(-999);
Java knows that Object.equals accepts a Object, and -999 fits an integer (the default type for a number), so it translates it to:
return listOfNumber.getFirst().equals(Integer.valueOf(-999));
Since a Integer and a Double aren't the same, it returns false, but for the == case, the java compilers gets smarter, and knows (double)-999 == (integer)-999

Comparison double value [duplicate]

This question already has answers here:
How to compare two double values in Java?
(7 answers)
Closed 7 years ago.
I have two double values. I want to check if two double values are same or not. I have two way to compare this double values.
First way :
double a = 0.1;
double b = 0.2;
if(a == b) {
System.out.println("Double values are same");
}
Another way to compare :
if(Double.compare(a, b) == 0) {
System.out.println("Double values are same");
}
Which one is the best way and accurate? Are both ways the same for comparison double values?
Double.compare handles the case of NaN and negative zeros differently than ==. For Double.compare, -0.0d is not equal to 0.0d.
For example the following code:
public static void main(String... args) {
double a = -0.0d;
double b = 0.0d;
if (a == b) {
System.out.println("a == b");
}
if (Double.compare(a, b) == 0) {
System.out.println("Double.compare(a, b) == 0");
}
}
will only print a == b.
The two operations are thus not equivalent. Using one over the other depend on your requirement.
The exact rule concerning == (and !=) can be found in the JLS, section 15.21.1:
Floating-point equality testing is performed in accordance with the rules of the IEEE 754 standard:
If either operand is NaN, then the result of == is false but the result of != is true. Indeed, the test x!=x is true if and only if the value of x is NaN.
Positive zero and negative zero are considered equal.
Otherwise, two distinct floating-point values are considered unequal by the equality operators. In particular, there is one value representing positive infinity and one value representing negative infinity; each compares equal only to itself, and each compares unequal to all other values.
Subject to these considerations for floating-point numbers, the following rules then hold for integer operands or for floating-point operands other than NaN:
The value produced by the == operator is true if the value of the left-hand operand is equal to the value of the right-hand operand; otherwise, the result is false.
The value produced by the != operator is true if the value of the left-hand operand is not equal to the value of the right-hand operand; otherwise, the result is false.
Let's analyze this part:
if(Double.compare(a, b) == 0)
By looking at the documentation of Double.compare, a possible implementation could be the following one (obviously it will be a more optimized one, but that's for the sake of the discussion):
return a == b ? 0 : (a < b ? -1 : +1);
Then, you have another comparison, so it becomes:
if((a == b ? 0 : (a < b ? -1 : +1)) == 0)
In the other case, you rely on a simple comparison using ==, that is:
if(a == b)
That said, in terms of accuracy I guess the result is the same, for the underlying representation of a double does not change and the comparison with 0 does not seem to affect the accuracy.
Which is the best?
Well, from the example above, I'd say the simpler one for you directly compare the values and you are interested only in equality, even though it's unlikely that you are facing with a problem which will benefit from choosing the best way for such a comparison.
Anyway, the approach using Double.compare is more suitable for those cases when you are not only interested in equality, but also in the concepts of greater than and/or less than.
Both of those options are perfectly valid for checking the equality of two numbers. I personally would say the == is nicer, but that's just me.
When double.compare() is better is when you want to know why your variables are not equal. It returns a little more information than true or false - a negative value if the left side is smaller, and a positive if the right side is smaller.

Java signed zero and boxing

Lately I've written a project in Java and noticed a very strange feature with double/Double implementation. The double type in Java has two 0's, i.e. 0.0 and -0.0 (signed zero's). The strange thing is that:
0.0 == -0.0
evaluates to true, but:
new Double(0.0).equals(new Double(-0.0))
evaluates to false. Does anyone know the reason behind this?
It is all explained in the javadoc:
Note that in most cases, for two instances of class Double, d1 and d2, the value of d1.equals(d2) is true if and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However, there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even though Double.NaN==Double.NaN has the value false.
If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0==-0.0 has the value true.
This definition allows hash tables to operate properly.
Now you might ask why 0.0 == -0.0 is true. In fact they are not strictly identical. For example:
Double.doubleToRawLongBits(0.0) == Double.doubleToRawLongBits(-0.0); //false
is false. However, the JLS requires ("in accordance with the rules of the IEEE 754 standard") that:
Positive zero and negative zero are considered equal.
hence 0.0 == -0.0 is true.
It important to undertand the use of signed zero in the Double class. (Loads of experienced Java programmers don't).
The short answer is that (by definition) "-0.0 is less than 0.0" in all the methods provided by the Double class (that is, equals(), compare(), compareTo(), etc)
Double allows all floating point numbers to be "totally ordered on a number line".
Primitives behave the way a user will think of things (a real world definition) ... 0d = -0d
The following snippets illustrate the behaviour ...
final double d1 = 0d, d2 = -0d;
System.out.println(d1 == d2); //prints ... true
System.out.println(d1 < d2); //prints ... false
System.out.println(d2 < d1); //prints ... false
System.out.println(Double.compare(d1, d2)); //prints ... 1
System.out.println(Double.compare(d2, d1)); //prints ... -1
There are other posts that are relevant and nicely explain the background ...
1: Why do floating-point numbers have signed zeros?
2: Why is Java's Double.compare(double, double) implemented the way it is?
And a word of caution ...
If you don't know that, in the Double class, "-0.0 is less than 0.0", you may get caught out when using methods like equals() and compare() and compareTo() from Double in logic tests. For example, look at ...
final double d3 = -0d; // try this code with d3 = 0d; for comparison
if (d3 < 0d) {
System.out.println("Pay 1 million pounds penalty");
} else {
System.out.println("Good things happen"); // this line prints
}
if (Double.compare(d3, 0d) < 0) { //use Double.compare(d3, -0d) to match the above behaviour
System.out.println("Pay 1 million pounds penalty"); // this line prints
} else {
System.out.println("Good things happen");
}
and for equals you might try ... new Double(d3).equals(0d) || new Double(d3).equals(-0d)
By using == statement you are comparing values. With equals your are comparing objects.

How to represent NaN in array of numbers?

The question says it all. I have an array of doubles and am doing something with them.
double expectedOutput[] = { 6.38792, 12.91079, 14.33333, 13.44517,
12.34539, 12.05397, 8.34061, 2.07900, -2.01999, -5.47802,
-8.21610, -9.26719, -11.02378 };
Ideally, i would test to see if
6.38792 == 6.38792 and end up with a 'pass'
Under certain conditions, i end up with the situation like
6.38792 != NaN
Knowing that this is a valid case sometimes, how can i represent NaN in my code?
I either need to include NaNs into my array of expected elements or somehow figure out that result is Not A Number
I am using Java
In Java, you can get NaN by using
Double.NaN
So you can just put this into your array.
If your question is how to check if something is NaN, you can call
Double.isNan(/* ... value ... */);
You'll have to test for it explicitly, since NaN != NaN, you can't just include it in your array. You have to use Double.isNaN(x).
double d = 0.0/0.0;
if(Double.isNan(d)){
// Double d is not a number.
}
Alternatively:
double d = Double.Nan;
if(Double.isNan(d)){
// Double d is not a number.
}
Since in many languages NaN is not equal to itself (and in Java also), you should handle it as a specific case. Use Float.NaN or Double.NaN to reference NaN. Use Float.isNaN or Double.isNaN to check if a specific value is NaN.
This is a case where Double objects actually are more useful than primitive doubles.
// auto-boxes them all to Double objects
Collection<Double> expectedOutput =
Arrays.asList(6.38792, 12.91079, 14.33333, 13.44517, 12.34539,
12.05397, 8.34061, 2.07900, -2.01999, -5.47802,
-8.21610, -9.26719, -11.02378, Double.NaN );
// maybe fill into HashSet for more efficient lookup?
// later:
double d = Double.NaN;
if(expectedOutput.contains(d)) {
System.out.println("found");
}
The reason is that Double.equals in fact implements the reflexivity condition of the equals contract, meaning that Double.valueOf(Double.NaN).equals(Double.valueOf(Double.NaN)) gives true, contrary to Double.NaN != Double.NaN.

Why is Java's Double.compare(double, double) implemented the way it is?

I was looking at the implementation of compare(double, double) in the Java standard library (6). It reads:
public static int compare(double d1, double d2) {
if (d1 < d2)
return -1; // Neither val is NaN, thisVal is smaller
if (d1 > d2)
return 1; // Neither val is NaN, thisVal is larger
long thisBits = Double.doubleToLongBits(d1);
long anotherBits = Double.doubleToLongBits(d2);
return (thisBits == anotherBits ? 0 : // Values are equal
(thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
1)); // (0.0, -0.0) or (NaN, !NaN)
}
What are the merits of this implementation?
edit: "Merits" was a (very) bad choice of words. I wanted to know how this works.
The explanation is in the comments in the code. Java has double values for both 0.0 and -0.0, as well as "not a number" (NaN). You can't use simple == operator for these values. Take a peek into the doubleToLongBits() source and at the Javadoc for the Double.equals() method:
Note that in most cases, for two
instances of class Double, d1 and d2,
the value of d1.equals(d2) is true if
and only if
d1.doubleValue() == d2.doubleValue()
also has the value true. However,
there are two exceptions:
If d1 and d2 both represent Double.NaN, then the equals method returns true, even
though Double.NaN == Double.NaN has the value false.
If d1 represents +0.0 while d2 represents -0.0, or vice versa, the equal test has the value false, even though +0.0 == -0.0 has the value true.
This definition allows hash tables to operate properly.
#Shoover's answer is correct (read it!), but there is a bit more to it than this.
As the javadoc for Double::equals states:
"This definition allows hash tables to operate properly."
Suppose that the Java designers had decided to implement equals(...) and compare(...) with the same semantics as == on the wrapped double instances. This would mean that equals() would always return false for a wrapped NaN. Now consider what would happen if you tried to use a wrapped NaN in a Map or Collection.
List<Double> l = new ArrayList<Double>();
l.add(Double.NaN);
if (l.contains(Double.NaN)) {
// this wont be executed.
}
Map<Object,String> m = new HashMap<Object,String>();
m.put(Double.NaN, "Hi mum");
if (m.get(Double.NaN) != null) {
// this wont be executed.
}
Doesn't make a lot of sense does it!
Other anomalies would exist because -0.0 and +0.0 have different bit patterns but are equal according to ==.
So the Java designers decided (rightly IMO) on the more complicated (but more intuitive) definition for these Double methods that we have today.
The merit is that it's the simplest code that fulfills the specification.
One common characteristic of rookie programmers is to overvalue reading source code and undervalue reading specifications. In this case, the spec:
http://java.sun.com/javase/6/docs/api/java/lang/Double.html#compareTo%28java.lang.Double%29
... makes the behavior and the reason for the behavior (consistency with equals()) perfectly clear.
That implementation allows a real number to be defined as < NaN, and -0.0 as < 0.0.

Categories

Resources