分类: C/C++
2014-12-30 10:27:40
整数的相等比较可以直接使用==来判断,但是浮点数的比较不能简单的用==来比较。用"=="来比较两个double应该相等的类型,返回真值完全是不确定的。计算机对浮点数的进行计算的原理是只保证必要精度内正确即可。我们在判断浮点数相等时,推荐用范围来确定,若x在某一范围内,我们就认为相等,至于范围怎么定义,要看实际情况而已了,float,和double 各有不同。那怎么对浮点数是否相等进行判断呢?-- 利用差值的绝对值的精度来判断。具体就是:f1和f2是两个浮点数,precision是我们自己设置的精度,比如1e-6。则可以用 fabs(f1-f2)<=precision 来判断f1和f2是否相等。如果要求更高的精度,则把precision定得更小就行了。
这个方法还存在问题:首先,precision是一个绝对的数据,也就是误差分析当中所说的绝对误差,使用一个固定的数值,对于float类型可以表达的整个数域来说是不可以的。比如precision取值为0.0001,而f1和f2的数值大小也是0.0001附近的,那么显然不合适。另外对于f1和f2大小是10000这样的数据的时候,它也不合适,因为10000和10001也可以真伪是相等的呢。适合它的情况只是f1或者f2在1或者0附近的时候。
解决方法:既然绝对误差不可以,那么自然的我们就会想到了相对误差。
这样写还不完善,因为是拿固定的第一个参数做比较的,那么在调用IsEqual(a, b, relError ) 和 IsEqual(b, a, relError ) 的时候,可能得到不同的结果。同时如果第一个参数是0的话,就有可能是除0溢出。这个可以改造:把除数选取为a和b当中绝对数值较大的即可
bool IsEqual(float a, float b, float relError )
{
if (fabs(a)>fabs(b)) return ( fabs((a-b)/a) > relError ) ? true : false;
else return (fabs( (a-b)/b) > relError ) ? true : false;
}
使用相对误差就很完善吗?也不是。当a和b都为0时,将出现除数为0的情况;并且在某些特殊情况下,相对误差也不能代表全部。比如在判断空间三点是否共线的时候,使用判断点到另外两个点形成的线段的距离的方法的时候,只用相对误差是不够的,因为线段距离可能很段,也可能很长,点到线段的距离,以及线段的长度做综合比较的时候,需要相对误差和绝对误差结合的方式才可以。相对完整的比较算法应该如下:
bool IsEqual(float a, float b, float absError, float relError )
{
if (a==b) return true ;
if (fabs(a-b)
else return (fabs((a-b)/b>relError ) ? true : false;
}