Рубрики
Без рубрики

Двойное сравнение в Java

Недавно я решал интересную ошибку, которая сводилась к сравнению двух двойных переменных с равными… Помеченный java.

Недавно я решал интересную ошибку, которая сводилась к сравнению двух двойных переменных с помощью метода равно . Это выглядит невинно, что может быть плохого в чем-то вроде first Double.equals(secondDouble) ? Проблема здесь заключается в том, как хранятся двойники. Чтобы уместить их в 64 байта (обычно), они округляются.

Смотрите пример ниже:

Double firstDouble = 0d;
for (int i = 1; i <= 42; i++) {
 firstDouble += 0.1;
}

Double secondDouble = 0.1 * 42;

System.out.println(firstDouble); // 4.200000000000001
System.out.println(secondDouble); // 4.2
System.out.println(firstDouble.equals(secondDouble)); // false

Эта неточность вызвана ошибками округления. Нам нужно использовать другой подход для сравнения этих двойников.

Пороговый способ

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

double epsilon = 0.000001d;
boolean result = Math.abs(firstDouble - secondDouble) < epsilon;
System.out.println(result); // true

Это небольшое число называется эпсилон, и чем оно меньше, тем выше точность результата. В большинстве случаев должно быть достаточно 5 знаков после запятой.

Математика Apache Commons

В JDK для этого нет служебного метода. К счастью для нас, математическая библиотека Apache Commons заботится о нас. С его помощью мы можем сравнить эти двойники следующим образом:

double epsilon = 0.000001d;
boolean result = Precision.equals(firstDouble, secondDouble, epsilon)
System.out.println(result);

Эпсилон имеет то же значение, что и в приведенном выше примере.

Аналогичные методы существуют в Guava и других библиотеках.

Вы можете следовать за мной по Твиттер чтобы получить больше подобных советов.

Оригинал: “https://dev.to/pavel_polivka/double-comparison-in-java-1b7”