大家都知道对于浮点数,计算机的存储是存在精度问题的,在做浮点数比较的时候,往往使用大于或者小于,很少使用等于号,但是在很多业务场景下,却很难避免相等的比较。由于浮点型的死区的存在,导致浮点数是无法使用等号进行比较的。浮点数存储的精度,就变成了“死区”。做不到是我们的技术问题,并不是用户的需求不合理。要解决死区的问题,首先要解决的就是精度问题。我们知道死区的存在,是因为浮点数在计算机中的存储是有精度的,那么如果在已知的精度需求下,是否可以解决浮点数相等的比较问题呢?答案当然是肯定的!
假设精度需求是小数点后9位,那么我们可以定义一个足够小的在精度范围以上的数值,例如DEAD_DIGIT = 0.0000000001,利用有效小数位数和浮点数的特点,进行数字相等的判断。
double DEAD_DIGIT = 0.0000000001;
const int TRUE = 1;
const int FALSE = 0;
/*
* compares d1 and d2, if d1 equals d2,
* returns 1, else returns 0;
*/
int doubleEqual(double d1, double d2)
{
if((d1 - DEAD_DIGIT < d2 && d1 + DEAD_DIGIT > d2) ||
(d2 - DEAD_DIGIT < d1 && d2 + DEAD_DIGIT > d1))
{
return TRUE;
}
else
{
return FALSE;
}
}
double DEAD_DIGIT = 0.000000001;
boolean doubleEquals(double d1, double d2){
return
(d1 - DEAD_DIGIT < d2 && d1 + DEAD_DIGIT > d2) ||
(d2 - DEAD_DIGIT < d1 && d2 + DEAD_DIGIT > d1);
}
在上述算法中,使用了精度外比较的方法,判断两个浮点数的相等。实际上,小于预定的精度的相等已经没有意义了,所以使用精度要求以外的大小比较,可以近似的认为两个数值的相等。在精度更高的领域,上述算法中的精度可以使用高精度的数据类型代替。比如如果是Java的实现的话,可以使用BigDecimal来代替double,而在C++中则没有更好的替换方案,可以使用char*类型,模拟一下,或者使用string.h,中定义的string类型,自己实现一个大数据运算类型。