Friday 15 July 2022

How to check two double values for equality?

Approach 1: Using == operator.

 

== operator return true, if the both the primitive operands has same value, else false. == operator return true, when two references point to same object, else false.

 

DoubleEqualityCheck1.java

package com.sample.app.numbers;

public class DoubleEqualityCheck1 {

	public static void main(String[] args) {
		double d1 = 12.34;
		double d2 = 12.34;
		double d3 = 12.3333339;

		System.out.println("d1 = %f".formatted(d1));
		System.out.println("d2 = %f".formatted(d2));
		System.out.println("d3 = %f".formatted(d3));

		System.out.println("\n(%f == %f) : %s".formatted(d1, d2, (d1 == d2)));
		System.out.println("(%f == %f) : %s".formatted(d1, d3, (d1 == d3)));

		// 0.0 == -0.0
		double d4 = 0.0;
		double d5 = -0.0;
		System.out.println("\n(%f == %f) : %s".formatted(d4, d5, (d4 == d5)));

		double d6 = Double.NaN;
		double d7 = Double.NaN;
		System.out.println("\n(%f == %f) : %s".formatted(d6, d7, (d6 == d7)));

	}

}

 

Output

d1 = 12.340000
d2 = 12.340000
d3 = 12.333334

(12.340000 == 12.340000) : true
(12.340000 == 12.333334) : false

(0.000000 == -0.000000) : true

(NaN == NaN) : false

 

We need to consider below points while using == operator for equality check.

 

a.   (+0.0 == -0.0) evaluates to  true, if you want to consider positive 0 is greater than negative 0, then you can use Double.compare method.

b.   Double.NaN == Double.NaN evaluates to false, use Double.compare method to treat them same.

 

If you have two Double objects, then you should not use == operator to check their value equality. == operator return true, when two references point to same object, else false.

 

Example

Double d1 = Double.valueOf(10);
Double d2 = Double.valueOf(10);
Double d3 = d1;

d1 == d2 will evaluate to false, since d1 and d2 point to two different objects.

d1 == d3 will evaluate to true, since d1 and d3 point to same object.

 

How to compare two Double objects using == operator?

Get the double primitive value by calling doubleValue() method and use == operator.

d1.doubleValue() == d2.doubleValue()

DoubleObjectsEqualityCheck1.java

package com.sample.app.numbers;

public class DoubleObjectsEqualityCheck1 {

    public static void main(String[] args) {

        Double d1 = Double.valueOf(10);
        Double d2 = Double.valueOf(10);
        Double d3 = d1;

        System.out.println("d1 = %f".formatted(d1));
        System.out.println("d2 = %f".formatted(d2));

        System.out.println("\n(d1 == d2) : %s".formatted((d1 == d2)));
        System.out.println("(d1 == d3) : %s".formatted((d1 == d3)));

        System.out.println("\n(d1.doubleValue() == d2.doubleValue()) : %s".formatted((d1.doubleValue() == d2.doubleValue())));

    }

}

Output

d1 = 10.000000
d2 = 10.000000

(d1 == d2) : false
(d1 == d3) : true

(d1.doubleValue() == d2.doubleValue()) : true

Approach 2: Using Double.compare method.

public static int compare(double d1, double d2)

Return 0 if d1 is numerically equal to d2,  a value less than 0 if d1 is numerically less than d2, and a value greater than 0 if d1 is numerically greater than d2.

 

Double.compare(0.000000, -0.000000) evaluated to 1

Double.compare method treats 0.0 is greater than to -0.0, so it is evaluated to 1.

 

Double.compare(NaN, NaN) is evaluated to 0.

 

Double.compare method internally use ‘Double.doubleToLongBits’ method to check the equality. Implementation looks like below.

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

    // Cannot use doubleToRawLongBits because of possibility of NaNs.
    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)
}

Double.doubleToLongBits method returns a representation of the specified floating-point value according to the IEEE 754 floating-point "double format" bit layout.

public static long doubleToLongBits(double value) {
    if (!isNaN(value)) {
        return doubleToRawLongBits(value);
    }
    return 0x7ff8000000000000L;
}

Find the below working application.

 

DoubleEqualityCheck2.java

package com.sample.app.numbers;

public class DoubleEqualityCheck2 {

    public static void main(String[] args) {
        double d1 = 12.34;
        double d2 = 12.34;
        double d3 = 12.3333339;

        System.out.println("d1 = %f".formatted(d1));
        System.out.println("d2 = %f".formatted(d2));
        System.out.println("d3 = %f".formatted(d3));

        System.out.println("\nDouble.compare(%f, %f) : %s".formatted(d1, d2, (Double.compare(d1, d2))));
        System.out.println("\nDouble.compare(%f, %f) : %s".formatted(d1, d3, (Double.compare(d1, d3))));

        // 0.0 == -0.0
        double d4 = 0.0;
        double d5 = -0.0;
        System.out.println("\nDouble.compare(%f, %f) : %s".formatted(d4, d5, (Double.compare(d4, d5))));

        double d6 = Double.NaN;
        double d7 = Double.NaN;
        System.out.println("\nDouble.compare(%f, %f) : %s".formatted(d6, d7, (Double.compare(d6, d7))));

    }

}

Output

d1 = 12.340000
d2 = 12.340000
d3 = 12.333334

Double.compare(12.340000, 12.340000) : 0

Double.compare(12.340000, 12.333334) : 1

Double.compare(0.000000, -0.000000) : 1

Double.compare(NaN, NaN) : 

Approach 3: Using Double#equals method. You can use this method when you have two Double objects to compare.


Double equals method also used doubleToLongBits internally, functionality is similar to Double.compare method on NaN,  0.0 and -0.0 checks.

public boolean equals(Object obj) {
    return (obj instanceof Double)
           && (doubleToLongBits(((Double)obj).value) ==
                  doubleToLongBits(value));
}

DoubleEqualsMethod.java

package com.sample.app.numbers;

public class DoubleEqualsMethod {

    public static void main(String[] args) {
        Double d1 = Double.valueOf(10.01);
        Double d2 = Double.valueOf(10.01);
        Double d3 = Double.valueOf(10.0099999);

        System.out.println("%f.equals(%f) : %s".formatted(d1, d2, d1.equals(d2)));
        System.out.println("%f.equals(%f) : %s".formatted(d1, d2, d1.equals(d3)));

        Double d4 = Double.valueOf(0.0);
        Double d5 = Double.valueOf(-0.0);
        System.out.println("\n%f.equals(%f) : %s".formatted(d4, d5, d4.equals(d5)));

        Double d6 = Double.NaN;
        Double d7 = Double.NaN;
        System.out.println("\n%f.equals(%f) : %s".formatted(d6, d7, d6.equals(d7)));

    }

}

Output

10.010000.equals(10.010000) : true
10.010000.equals(10.010000) : false

0.000000.equals(-0.000000) : false

NaN.equals(NaN) : true



You may like

Interview Questions

Can enum implement an interface in Java?

What happen to the threads when main method complete execution

Why System.out.println() is not throwing NullPointerException on null references?

Why should we restrict direct access to instance properties?

Closeable vs AutoCloseable in Java

What is the behaviour of static final method in Java?

No comments:

Post a Comment