3

为了比较 C 中的两个双精度类型变量,我定义了#define EQUALITY_EPSILON = 1e-8. 我正在做如下比较:

if((img_score[i] - img_score[j]) >= EQUALITY_EPSILON){
    // handle for ith score greater than jth score
}
else if((img_score[j] - img_score[i]) >= EQUALITY_EPSILON){
    // handle for ith score smaller than jth score
}
else{
    // handle for ith score equal to jth score
}

我面临的问题是我的代码中的分数非常小,因此对于EQUALITY_EPSILON = 1e-8,在某些情况下,比较的结果是相等的。我的问题是我可以设置多小EQUALITY_EPSILON

4

3 回答 3

14

浮点数在数轴上分布不均匀。它们在 0 附近非常密集,并且随着幅度的增加,两个可表达值之间的“增量”增加:

                               0
|      |     |    |   |  |  | ||| |  |  |   |    |     |      |

这意味着,对于小数字,您需要使用较小的“epsilon”。

编辑:并且您允许的错误或 epsilon 应该与您在比较的值中已经期望的错误在同一范围内。即由于产生它们的浮点运算而导致的错误。请参阅下面的评论了解原因。/编辑)。

您需要使用的“epsilon”类型的一个公平指示可以从以下位置nextafter获得math.h

nextafter(x, y)返回 之后的下一个可表示值x,当沿着数轴在 的方向移动时y

另一种方法是计算 和 之间的幅度差异img_score[i],并查看它与或img_score[j]的幅度相比有多小。小了多少?你需要决定。img_score[i]img_score[j]

于 2012-08-20T13:07:15.840 回答
2

您不应该对 epsilon 使用绝对值。选择的值应该与您正在比较的值相关。

例如,您可以将最小的(最接近于零的)除以一百万并使用其绝对值。

这是否是一个合适的选择取决于执行了哪些操作来达到这些值。它可能并不适合所有情况。

于 2012-08-20T12:44:57.750 回答
1

双精度的最小绝对值是 2^{-1023},大约是 10^{-308}。但是只有 53 位用于存储尾数(有效数字所在的部分)。如果您事先知道差异的近似值,那么您的 epsilon 几乎可以低至该差异的 2^{-53} 倍。如果您事先不知道,您可能应该将您的 epsilon 构建为差异之一的百分比。

Note that going down to 2^{-53} times the difference is the limit caused by the limited precision in the double. If the two values you are subtracting are so close to each other that you have fewer than 53 significant bits in their difference, your epsilon could only go as low as 2^{-x} times the difference, where x is the number of significant bits in the difference.

于 2012-08-20T13:08:35.043 回答