Java, похоже, не сравнивает Doubles правильно
Вопрос
Я создал связанный список с функциями вставки, поиска и удаления.Я также создал для него итератор.Теперь предположим, что я делаю это:
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 неправильно сравнивает числа.
РЕДАКТИРОВАТЬ:кстати, BigDecimal тоже доставил мне такую же проблему.
РЕДАКТИРОВАТЬ 2:Equals() сработало, не осознавая, что что-то еще не так.Извини.
Решение
Вам не нужен для этого оператор !=.Он сравнивает ссылки.Вы хотите .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))
является ложным.
Другие советы
Обратите внимание, что использование .equals()
сравнивать парный разряд может привести к ошибкам. 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)