У меня есть 2 вещественных числа, например типа double. Я хочу их сравнить на равенство с заданной точность. Как правильно выполнять такое сравнение?
Пока в голову приходит такой вариант:
double x, y;
...
public boolean isEqual(double x, double y, double eps){
return Math.abs(x-y) < eps;
}
Кажется, что в Java должны быть встроенные способы сравнить 2 вещественных числа. Такие существуют?
Ответ
Вообще, это довольно интересный вопрос.
Да, в общем случае всегда рекомендуется использовать что-то вроде:
bool isEqual = fabs(a1 – a2) <= epsilon;
Но более интересный вопрос, какое значение для epsilon использовать.
К примеру, в C++ в float.h есть константа FLT_EPSILON, равная 1E-5. Всё, можно такое же значение использовать, да?
Вполне, если числа большие. Но если у вас число в промежутке [0;1], то начинаются проблемы. Точность вычисления будет соизмерима с фактическим значением, что приведёт к тому, что на такое сравнение нельзя будет положиться.
Относительный эпсилон
Для сравнения чисел можно руководствоваться правилом:
Для сравнения a1 и a2 вычисляем diff = fabs(a1-a2). Если diff меньше
,чем n% от max(abs(a1), abs(a2)), тогда a1 и a2 можно считать равными.
public static bool almostEqualRelative(float a, float b,
float maxRelDiff = FLT_EPSILON) {
// находим разницу
float diff = fabs(a - b);
A = fabs(a);
B = fabs(b);
// находим большее
float largest = (b > a) ? b : a;
if (diff <= largest * maxRelDiff)
return true;
return false;
}
Более сложно и подробней про это можно почитать в этой занятной статье.
Комментариев нет:
Отправить комментарий