解决两个浮点数是否相等

来源:互联网 发布:飞扬软件手游 编辑:程序博客网 时间:2024/05/22 11:32

整数的相等比较可以直接使用==来判断,但是浮点数的比较不能简单的用==来比较。那怎么对浮点数是否相等进行判断呢?– 利用差值的绝对值的精度来判断。具体就是: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附近的时候。

解决方法:既然绝对误差不可以,那么自然的我们就会想到了相对误差。
bool IsEqual(float a, float b, float relError ){    return ( fabs ( (a-b)/a ) < relError ) ? true : false;}

relError : 相对误差

这样写还不完善,因为是拿固定的第一个参数做比较的,那么在调用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) < absError )         return true ;    if (fabs(a) > fabs(b))         return (fabs((a - b) / a > relError ) ? true : false;    else         return (fabs((a - b) / b > relError ) ? true : false;}

absError :绝对误差。
relError : 相对误差。