Epsilon 根据双倍范围内的值而变化。如果您想使用您的自己的和固定 epsilon,我建议为1 选择一个epsilon。
fabs(a1-a2) < epsilon
这并不完美。如果a1 和a2 是小数运算的结果,则ε 会很小。如果 a1 和 a2 是大数字运算的结果,那么 epsilon 会很大。
fabs((a1-a2)/a2) < epsilon
这会更好一些,因为您希望将 epsilon 缩放到 a2。但是,如果 a2 等于 0,则除以 0。
fabs(a1-a2) < fabs(a2)*epsilon
这有点好。但是,如果 a2 等于 0,则这是不正确的。 fabs(a2)*epsilon 将等于 0 并且两个值 a1=0.000000001 和 a2=0 的比较将始终失败。
fabs(a1-a2) < max(fabs(a1), fabs(a2))*epsilon
这有点好。但是,这是不正确的,因为epsilon 在连续 方式中不成比例。使用 IEEE 编码,epsilon 与基于 2 的 离散 方式的值成比例。
fabs(a1-a2) < 2^((int)log2(max(fabs(a1), fabs(a2)))*epsilon
当a1 和a2 不等于0 时,这对我来说是正确的。
泛型方法的实现可以是:
bool nearly_equal(double a1, double a2, double epsilon)
{
if (a1 == 0 && a2 == 0)
return true;
return std::abs(a1 - a2) < epsilon * pow (2.0, static_cast<int> (std::log2(std::max(std::abs(a1), std::abs(a2)))));
}