views:

1544

answers:

2

I created a Linked List, with insert, search and remove functions. I also created a iterator for it. Now, suppose I do this:

myList<Integer> test = new myList();
test.insert(30);
test.insert(20);
test.insert(10);
myList.iterator it = test.search(20);
if(it.hasNext())
    System.out.println(it.next());

And voila, it works (it prints the value of the element at the node, in this case 20). Now, if I do this:

myList<Double> test = new myList();
test.insert(30.1);
test.insert(20.1);
test.insert(10.1);
myList.iterator it = test.search(20.1);
if(it.hasNext())
    System.out.println(it.next());

It doesn't, because the iterator is pointing to null. Here is the implementation of the search function:

public iterator search(T data)
{
    no<T> temp = first;
    while( (temp != null) && (temp.data != data) )
     temp = temp.next;
    return (new iterator(temp));
}

Here's how I know there's something fishy with the comparisons: If I change part of the above code like this:

while( (temp != null) && (temp.data != data) )
     System.out.println(temp.data + " " + data);
     temp = temp.next;

I can see it printing the numbers in the list. It prints, at one point, "20.1 20.1" (for example). So how can I fix this? The function appears to be right, but it just seems as if Java isn't comparing the numbers correctly.

EDIT: wth, BigDecimal gave me the same kind of problem too.

EDIT 2: equals() worked, didn't realize something else was amiss. Sorry.

+2  A: 

You don't want the != operator for this. It comapres references. You want the .equals() method:

public iterator search(T data)
{
    no<T> temp = first;
    while (!data.equals(temp.data)) {
        temp = temp.next;
    }
    return (new iterator(temp));
}

Also, watch out for auto-boxing. You may find that test.search(20.1) boxes 20.1 to a Float not a Double, which will probably break your comparison. Compare the results with test.search(20.1d). If I recall correctly, the expression:

new Float(20.1).equals(new Double(20.1))

is false.

cletus
The constant 20.1 in Java is always interpreted as a double, i.e. 20.1d. So 20.1 will always autobox to a Double. Float has a constructor that takes double (oddly, I think) which is why your second example compiles without error.
Dave Ray
Beware of equality comparisons in IEEE 754 format (http://en.wikipedia.org/wiki/IEEE_754). If the numbers where calculated you may end up finding that 0.2 is not equal to 1/5 (don't know the exact example) due to representation and/or rounding issues.
David Rodríguez - dribeas
Boxing of ints in -128 to 127 inclusive is required to return the same Integer every time (may do for other values to). Which is why the Integer version happens to work. FindBugs will (probably) warn you if use ==/!= incorrectly.
Tom Hawtin - tackline
+7  A: 

Note that using .equals() to compare doubles may lead to errors. Double.equals() uses this as its equality test:

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

Doubles and floats are approximations of numbers stored in a fixed amount of memory. In order to properly compare floating point numbers you need to be aware that due to the nature of floats, there will be some error.

see: http://www.google.com/search?q=floating+point+equality

a quick and easy way to compare doubles is to use Math.abs(a-b)<ACCEPTABLE_ERROR where ACCEPTABLE_ERROR could be .000000000001 depending on what exactly your doing. (Note this doesn't handle edge cases such as NaN and INFINITY)

argonide