проверка исходного кода дает мне это (я вырезал реализации для диапазонов)
bool approxEqual(T, U, V)(T lhs, U rhs, V maxRelDiff, V maxAbsDiff = 1e-5)
{
if (rhs == 0)
{
return fabs(lhs) <= maxAbsDiff;
}
static if (is(typeof(lhs.infinity)) && is(typeof(rhs.infinity)))
{
if (lhs == lhs.infinity && rhs == rhs.infinity ||
lhs == -lhs.infinity && rhs == -rhs.infinity) return true;
}
return fabs((lhs - rhs) / rhs) <= maxRelDiff
|| maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
}
эта последняя строка - то, что нам нужно изучить:
return fabs((lhs - rhs) / rhs) <= maxRelDiff
|| maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
другими словами, функция возвращает true, если числа либо относительно отличаются не более чем на коэффициент maxRelDiff
ИЛИ абсолютно отличаются не более чем на maxAbsDiff
, поэтому при использовании maxRelDiff
из 0.01
(или 1E-2
) сравнивается с точностью до 2 (десятичных) цифр
и при использовании maxAbsDiff
, отличного от 0, допускаются числазначение, близкое к 0, считается равным, хотя относительная разница больше, чем maxRelDiff
edit : сначала необходимо решить, насколько точным должно быть сравнение, и выбрать maxRelDiff
на основезатем определите, в какой точке число должно быть равно 0
, с примерами в комментариях:
approxEqual(1+1e-10, 1.0, 1e-10, 1e-30)
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30)
. Здесь сравниваются значения, близкие к 1, поэтому maxRelDiff
имеет преимущество и выбираетлюбой maxAbsDiff
(ниже maxRelDiff
) не изменитсячто-нибудь
approxEqual(0, 1e-10, 1e-10, 1e-30)
approxEqual(0, 1e-9, 1e-9, 1e-30)
это сравнивает значения от 0 до 0, поэтому RelDiff (fabs((lhs - rhs) / rhs)
) будет 1 и maxAbsDiff
козыри