为了比较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
有多小?
答案 0 :(得分:13)
浮点数不会均匀地分布在数字线上。它们在0附近非常密集,随着幅度的增加,两个可表达值之间的“delta”增加:
0
| | | | | | | ||| | | | | | | |
这意味着,对于较小的数字,您需要使用较小的“epsilon”。
(编辑:并且您允许的错误或epsilon应该与您在比较的值中预期的错误处于相同的范围内。即由于浮点运算导致的错误制作它们。请参阅下面的评论,了解原因。 / EDIT )。
math.h
中的nextafter
可以获得您需要使用的'epsilon'类型的公平指示:
nextafter(x, y)
返回x
之后的下一个可表示值,沿着数字线行进,方向为y
。
另一种方法是计算img_score[i]
和img_score[j]
之间的幅度差异,并查看它与img_score[i]
或{{1}的幅度相比有多小}。多小了?你需要决定。
答案 1 :(得分:2)
您不应该使用epsilon的绝对值。选择的值应该与您要比较的值相关。
例如,您可以将最小值(最接近零)除以一百万并使用其绝对值。
这是否合适的选择取决于为达到这些值而执行的操作。它可能并不适合所有情况。
答案 2 :(得分:1)
double的最小绝对值是2 ^ { - 1023},大约是10 ^ { - 308}。但是只有53位用于存储尾数(有效数字所在的部分)。如果您事先知道差异的近似值,那么您的epsilon的差值几乎可以低至2 ^ { - 53}倍。如果您事先不知道,您应该将您的epsilon构建为其中一个差异的百分比。
请注意,下降到2 ^ { - 53}倍的差异是双精度限制所造成的限制。如果你减去的两个值彼此非常接近,那么你的差值中有少于53个有效位,那么你的epsilon只能低至差值的2 ^ { - x}倍,其中x是有效值的数量不同之处。