2

This question comes after this piece of code (an implementation of binary search). I would appreciate if someone could tell me why this is not outputting the expected answer:

public static void main(String[] args){
    Double[] array = {0.0,1.0,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0};
    BinarySearch s = new BinarySearch(array);
    System.out.println(s.searchNextHighest(2.0));
}

public BinarySearch(Double[] array){
    numbers = array;
}

public Integer searchNextHighest(Double y){
    return binarySearchNextHighest(0, numbers.length-1, y, numbers);
}

public Integer binarySearchNextHighest(int min, int max, Double target, Double[] array){
    int mid = (min+max)/2;

    if(target==array[mid]){ //Fails here
        return mid;
    }

    if(max<min){
        if(min>=array.length) return null;
        return mid;
    }

    if(target>array[mid]){
        return binarySearchNextHighest(mid+1, max, target, array);
    }else{
        return binarySearchNextHighest(min, mid-1, target, array);
    }
}

Output: 1

I followed through a debugger and made absolute sure. At a certain moment, target = 2.0, and mid=2, and array[mid] = 2.0. Yet the if statement does not execute.

Curiously, this error does not occur when Integer arrays/targets are used.

What is happening here? I thougt these things only happened when comparing very big numbers. What other pitfalls exist?

[EDIT] Here is a simplified version:

public static void main(String[] args){
    Double[] array = {2.0};
    Double target = 2.0;
    if(array[0] == target) System.out.println("Yay!");
}

Output: None

[EDIT2]

public static void main(String[] args){
    double[] array = {3.0};
    double target = 3.0;
    if(array[0] == target) System.out.println("Yay!");
}

Output: Yay!

Someone in comments pointed out that this error was a result of comparing objects. Why isn't it automatically unpacking?

[EDIT3] Here is code using the Integer object:

public static void main(String[] args){
    Integer[] array = {3};
    Integer target = 3;
    if(array[0] == target) System.out.println("Yay!");
}

Output: Yay!

So I guess the reason is obvious, but why is the object Integer implemented so differently? That is automatically unpacks itself.

user2316667
  • 5,444
  • 13
  • 49
  • 71

2 Answers2

6

double and Double are two different things. Double creates an object and they will be equal if they are pointing to the same address in memory. The values they are holding can be the same, but they are different objects, so not equal. Same with Integer. For your code you can use double instead or compare through .doubleValue() or .equals() method for Double to compare the values.

EDIT: As pointed out by @MarkPeters and @TedHopp in comments, Integer behaves a bit differently, more info here.

sashkello
  • 17,306
  • 24
  • 81
  • 109
  • 1
    But it actually works with Integer. I get the correct output. Any reason for this difference? – user2316667 Aug 26 '13 at 04:42
  • 3
    @user2316667: It's a nuance of the JVM. Integers from -128 to 127 (minimally; greater ranges are permitted) inclusive are cached such that if you autobox an `int` in that range into an `Integer`, it will use a shared instance. See [the docs for `Integer.valueOf()`](http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#valueOf(int)). Give it a try with big numbers, say over `1000000`. – Mark Peters Aug 26 '13 at 04:43
  • @user2316667 - Integer caches a range of smaller int values, so when you autobox 2 and autobox 2 again, you get the same object. That doesn't happen with `Double`; you get a new object every time. – Ted Hopp Aug 26 '13 at 04:43
  • I think if you are comparing Integer to int, it will work. I'm not sure about Integer and Integer... – sashkello Aug 26 '13 at 04:43
3

use the equals() method to compare content of two objects.

 if(target.equals(array[mid])){
    return mid;
}  

According to Double#equals

Compares this object against the specified object. The result is true if and only if the argument is not null and is a Double object that represents a double that has the same value as the double represented by this object.

Please also look into What's the difference between ".equals" and "=="?

Community
  • 1
  • 1
Prabhaker A
  • 8,317
  • 1
  • 18
  • 24