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.