epsilon()
is only the difference between 1.0
and the next value representable after 1.0
, the real min. The library function std::nextafter
can be used to scale the equality precision test for numbers of any magnitude.
For example using std::nextafter
to test double
equality, by testing that b is both <= next number lower than a && >= next number higher than a:
bool nearly_equal(double a, double b)
{
return std::nextafter(a, std::numeric_limits<double>::lowest()) <= b
&& std::nextafter(a, std::numeric_limits<double>::max()) >= b;
}
This of course, would only be true
if the bit patterns for a & b are the same. So it is an inefficient way of doing the (incorrect) naive direct a == b comparrison, therefore :
To test two double
for equality within some factor scaled to the representable difference, you might use:
bool nearly_equal(double a, double b, int factor /* a factor of epsilon */)
{
double min_a = a - (a - std::nextafter(a, std::numeric_limits<double>::lowest())) * factor;
double max_a = a + (std::nextafter(a, std::numeric_limits<double>::max()) - a) * factor;
return min_a <= b && max_a >= b;
}
Of course working with floating point, analysis of the calculation precision would be required to determine how representation errors build up, to determine the correct minimum factor.