不能用等号判断两个小数是否相等
极理想情况下,判断两个实数 a 和 b 相等,这里不妨将两个数分别定义为double型,1.0000001 和 1.0 这两个数在绝大多数的情况下,认为它们是相等的,所以经常能看到如下的 C 或者 C++ 代码 if(fabs(a-b)<=eps_0) ,一般地,eps_0设置为很小的数,比如1.0e-6 或者 1.0e-7,直观地来讲,就是说当两个数之间的距离(称为绝对误差)很小很小的时候,我们就认为它们是相等的。
如果数字的数量级很大时,比如下面这两个数10000.0001和10000.000,显然使用上述的距离判断的结果两者不相等,不过,我们来看它们之间的相对误差为(1000.0001-10000.000) /10000.000=1.0e-9,那么这两者也应该认为是相等的,于是使用相对误差的想法,将代码改写为 if(fabs(a-b)<=eps*fabs(a)) 。
使用相对误差可以回避掉数字数量级较大的问题,不过,它对于数量级较小的问题解决起来效果不佳,考虑一种极端情况,比如被比较的两个数字分别为 a=0.0 和 b=0.00000001,这个时候这两个数字相差很小,认为相等,但是使用相对误差的代码时,由于右端项为零,而左端项大于零,显然等式不成立,即使用该方法判断两个数字并不相等。 比较完善的方式是将绝对误差和相对误差结合起来考虑,来设计C++代码:
bool isEqual(const double a, const double b)
{
const eps_0 = 1.0e-6, rel_error = 10e-4;
bool isEqualFlag = FALSE;
if(fabs(a-b)<=eps_0)//绝对误差
{
isEqualFlag = TRUE;
}
else{
if(fabs(a) >= 1000.0)//相对误差
{
if(fabs(a-b)<=rel_error*fabs(a))
{
isEqualFlag = TRUE;
}
}
}
return isEqualFlag;
}
浮点数判等思路总结如下:
- 对于数量级较小——绝对误差
- 对于数量级较大——相对误差
可以把苛刻的条件放大,本来fabs(a-b)必须小于10e-6才判定相等,但是因为数据的数量级比较大,所以经过与fabs(a)相乘来将条件放宽,小于10e-4就可以判定相等。