2

I was going through:

Why is a round-trip conversion via a string not safe for a double?

and just wanted to see what happens such situations in Java.

public class RounfTripConversion {

    public static void main(String[] args) {
        Double d1 = 0.84551240822557006;
        String s = d1.toString(); // String("r");
        Double d2 = Double.parseDouble(s);
        System.out.println("Double 1:" + d1);
        System.out.println("Double 2:" + d2);
        boolean equal = d1 == d2;
        System.out.println("Double 1 and 2 are EQUAL is " + equal);
        System.out.println("Double 1 - Double 2=" + (d1 - d2));
    }
}

Output:

Double 1:0.8455124082255701
Double 2:0.8455124082255701
Double 1 and 2 are EQUAL is false
Double 1 - Double 2=0.0

Can someone help me understand why a boolean comparison that returns both d1 and d2 are not identical, although that's the case?

Community
  • 1
  • 1

4 Answers4

2

Because Double is a class so d1 and d2 point to different objects:

Double d1 = 0.84551240822557006;
String s = d1.toString();
Double d2 = Double.parseDouble(s);

boolean equal = d1 == d2; << FALSE

But the value of the double stored in the Double will return true when compared:

boolean equal = d1.doubleValue() == d2.doubleValue(); << TRUE

What confuses you i think is the difference between double and Double. Where double is a primitive type, just the value, and Double is a wrapper class that contains the value.

What happens here is autoboxing. You write the following:

Double d1 = 0.84551240822557006;

But what really happens is:

Double d1 = new Double(0.84551240822557006);

So you have a reference to a Double class that contains a double.

If you would do:

double d1 = 0.84551240822557006;

Then you would have just the value and not a reference to a class that contains the value.

fonZ
  • 2,428
  • 4
  • 21
  • 40
0

Both the Double values are identical but not pointing to the same reference.

Look at compare() method in Double class.

Suresh Atta
  • 120,458
  • 37
  • 198
  • 307
-1

While in this case, suresh has a point about it doing an object comparison, even using two doubles would give you false.

Floating point numbers (float and double) are stored as a mathematical expression. Converting a double to a String will truncate it. So, the new double after converting it back will not have the same value as the original.

Powerlord
  • 87,612
  • 17
  • 125
  • 175
-1

When comparing floating point numbers, in this case a double boxed into a Double, you need to take care to use an epsilon to compare the actual values. The reasons are detailed in this excellent article by Bruce Dawson.

What you really want is something more akin to isNearlyEqual. People expect equal to be transitive. At the very least, you need to convey the idea that it is no longer transitive.

To that end, you shouldn't do exact comparisons. From this answer:

double a = 1.000001;
double b = 0.000001;
double c = a-b;
if (Math.abs(c-1.0) <= 0.000001) {...}

In your case, you are comparing the references to two Double, which doesn't compare the actual value.

Community
  • 1
  • 1
Engineer2021
  • 3,288
  • 6
  • 29
  • 51
  • 1
    You make it more complicated then it is, my answer was absolutely correct, simpler to understand and given 10 minutes earlier. – fonZ Jun 24 '14 at 21:46
  • -1 to @fonZ and 1+ to staticx. fonZ your answer is absolutely wrong. Floating point equality is never absolute, and staticx "over complications" are in fact necessary. – Hovercraft Full Of Eels Jun 24 '14 at 21:52
  • @HovercraftFullOfEels ok, tell me exactly what is wrong instead of downvoting without explaination? – fonZ Jun 24 '14 at 21:53
  • @fonZ: I already stated why. Floating point equality is never absolute, and staticx "over complications" are in fact necessary. – Hovercraft Full Of Eels Jun 24 '14 at 21:55
  • 1
    @HovercraftFullOfEels that is totally off topic, the op is asking why his comparison doesnt return true. – fonZ Jun 24 '14 at 21:55
  • In this particular case, the API promises exact value equality, so there is no need for an epsilon to check whether it is working. – Patricia Shanahan Jun 24 '14 at 22:53
  • @Patricia: if using .equals, but OP is using == instead. .equals uses doubleToLongbits – Engineer2021 Jun 24 '14 at 23:14