Java, кажется, не сравнивает Doubles правильно - PullRequest
1 голос
/ 26 декабря 2008

Я создал связанный список с функциями вставки, поиска и удаления. Я также создал для этого итератор. Теперь предположим, что я делаю это:

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());

И вуаля, это работает (печатает значение элемента в узле, в данном случае 20). Теперь, если я сделаю это:

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());

Нет, потому что итератор указывает на ноль. Вот реализация функции поиска:

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

Вот как я узнаю, что в сравнениях есть что-то подозрительное: если я изменю часть вышеприведенного кода следующим образом:

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

Я вижу, как он печатает числа в списке. Он печатает, в какой-то момент, «20,1 20,1» (например). Так как я могу это исправить? Функция кажется правильной, но кажется, что Java неправильно сравнивает числа.

РЕДАКТИРОВАТЬ: wth, BigDecimal дал мне такую ​​же проблему.

РЕДАКТИРОВАТЬ 2: equals () работал, не понимал, что что-то еще было неправильно. К сожалению.

Ответы [ 2 ]

11 голосов
/ 26 декабря 2008

Обратите внимание, что использование .equals() для сравнения doubles может привести к ошибкам. Double.equals() использует это как критерий равенства:

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

Двойные значения и с плавающей запятой являются приближениями чисел, хранящихся в фиксированном пространстве в памяти.

Для правильного сравнения чисел с плавающей запятой необходимо помнить, что из-за природы чисел с плавающей точкой будет некоторая ошибка.

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

Быстрый и простой способ сравнения пар - использовать Math.abs(a-b)<ACCEPTABLE_ERROR где ACCEPTABLE_ERROR может быть .000000000001 в зависимости от того, что именно вы делаете. (обратите внимание, что это не обрабатывает крайние случаи, такие как NaN и INFINITY)

2 голосов
/ 26 декабря 2008

Вам не нужен оператор! = Для этого. Это сопоставляет ссылки. Вы хотите .equals() метод:

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

Также следите за автобоксом . Вы можете обнаружить, что test.search(20.1) поля от 20,1 до Float не Double, что, вероятно, нарушит ваше сравнение. Сравните результаты с test.search(20.1d). Если я правильно помню, выражение:

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

неверно.

...