checking the source code gives me this (I cut out the implementations for the ranges)
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;
}
this last line is what we'll need to study:
return fabs((lhs - rhs) / rhs) <= maxRelDiff
|| maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
in other words the function returns true if the numbers are either relatively different by no more than a factor of maxRelDiff
OR absolutely different by no more than maxAbsDiff
so using a maxRelDiff
of 0.01
(or 1E-2
) compares with an accuracy of 2 (decimal) digits
and using maxAbsDiff
different from 0 allows numbers close to 0 to be considered equal even though there relative difference is greater than maxRelDiff
edit: basically first decide how accurate the comparison needs to be and choose your maxRelDiff
based on that, then decide at what point should a number be equal to 0
with the examples in the comments:
approxEqual(1+1e-10, 1.0, 1e-10, 1e-30)
approxEqual(1+1e-10, 1.0, 1e-9, 1e-30)
this compares values close to 1 so maxRelDiff
trumps here and choosing any maxAbsDiff
(lower than maxRelDiff
) wont change anything
approxEqual(0, 1e-10, 1e-10, 1e-30)
approxEqual(0, 1e-9, 1e-9, 1e-30)
this compares values close to 0 to 0 so the RelDiff (fabs((lhs - rhs) / rhs)
) will be 1 and maxAbsDiff
trumps