checking the source code gives me this (I cut out implementations for 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; }
The last line is what we need to learn:
return fabs((lhs - rhs) / rhs) <= maxRelDiff || maxAbsDiff != 0 && fabs(lhs - rhs) <= maxAbsDiff;
In other words, the function returns true if the numbers either differ from each other by no more than a factor maxRelDiff OR are completely different no more than by maxAbsDiff
therefore, using maxRelDiff of 0.01 (or 1E-2 ) is compared to within 2 (decimal) digits
and using maxAbsDiff other than 0 allows us to consider numbers close to 0 equal, although the relative difference is greater than maxRelDiff
edit : first, first determine how accurate the comparison should be, and select your maxRelDiff based on this, then determine at what point the number 0 should be
with 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 (below maxRelDiff ) will not change anything
approxEqual(0, 1e-10, 1e-10, 1e-30) approxEqual(0, 1e-9, 1e-9, 1e-30)
it compares the value close to 0 to 0, so RelDiff ( fabs((lhs - rhs) / rhs) ) is 1 and maxAbsDiff trumps