C语言中,双精度数据类型的最高精度是多少?

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 设定得多小?


7
你考虑过使用相对误差吗?http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/ - cnicutar
必读:epsilon不是0.0001 - Damon
1
浮点数值中的错误取决于先前的操作。确定可接受的误差阈值需要分析先前的操作(误差可能有多大)和比较的目的(可以容忍多大的误差)。没有额外信息,无法给出正确的答案。 - Eric Postpischil
3个回答

14

浮点数在数轴上不是均匀分布的。它们在0附近非常密集,随着数量级的增加,在两个可表示值之间的“差”也会增加:

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

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

(编辑:并且你允许的错误或epsilon应该与你已经预期在比较值中存在的浮点运算误差一样大小。请参见下面的评论以了解原因。 /编辑).

可以从math.h中的nextafter获得你需要使用的“epsilon”的公平指示:

nextafter(x, y)返回沿着数线向y方向移动时x后面的下一个可表示值。

另一种方法是计算img_score[i]img_score[j]之间的大小差异,并查看它相对于img_score[i]img_score[j]的大小有多小。有多小?你需要决定。


谢谢Arjun!如果我不需要相等性检查,那么直接比较像if(img_score[i] > img_score[j])这样也可以工作,对吧? - stressed_geek
2
@stressed_geek 是的,它会。所有比较当然都是“正确”的。因此,如果一个值更大(即使只有 nextafter 的差异),它也将显示为 > - ArjunShankar
被比较的数字的大小以及该区域中浮点数的间距与之前操作产生的误差大小无关。这个问题没有提供任何可以限制误差的信息,因此无法给出可靠的建议来补偿误差。 - Eric Postpischil
@stressed_geek - 上面的评论让我觉得你应该重新考虑你的问题。实质上,Eric Postpischil所说的是正确的。你必须考虑你的FP算术产生的错误类型。 - ArjunShankar

2

在使用epsilon时,不应该使用绝对值。选择的值应该相对于要比较的值。

例如,您可以将最小值(最靠近零点)除以一百万,并使用那个绝对值。

是否适合取决于达到这些值所执行的操作。它可能并不适用于所有情况。


谢谢。当您说“最小”时,您能否澄清您指的是什么? - stressed_geek
@stressed_geek:非常好的观点。我是指最小绝对值:最接近零,而不是最接近负无穷大。 - paxdiablo
明白了,再次感谢。此外,如果我不需要进行相等性检查,那么直接比较如 if(img_score[i] > img_score[j]) 也可以正常工作,对吧? - stressed_geek
如果你要进行这种愚蠢的epsilon比较,那么epsilon的值应该是(fabs(a)+fabs(b))*DBL_EPSILON*K,其中K是一些小常数,大致对应于计算ab时发生的舍入步骤数量。 - R.. GitHub STOP HELPING ICE
被比较的数字的大小以及该区域中浮点数的间距与之前操作产生的误差大小无关。这个问题没有提供任何可以限制误差的信息,因此无法给出可靠的建议来补偿误差。 - Eric Postpischil

1
双精度浮点数的最小绝对值是2^{-1023},约为10^{-308}。但只有53位用于存储尾数(即重要数字所在的部分)。如果您事先知道差异的近似值,则可以将epsilon降至2^{-53}乘以该差异的水平。如果您不知道事先的情况,那么您应该将epsilon建立为其中一个差异的百分比。
请注意,将差异降至2^{-53}是由于双精度浮点数的有限精度造成的极限。如果您要减去的两个值非常接近,其差异中只有少于53个有效位,则您的epsilon只能降至2^{-x}乘以差异,其中x是差异中有效位的数量。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接