检查传递的double参数是否“足够接近”以被视为整数

时间:2014-11-06 11:25:38

标签: c++ rounding-error

我正在编写一个代码,我需要检查一个可以采用double值的变量是否实际上采用了一个整数值。我认为双变量如果在整数的容差范围内,则采用整数值。这个公差是1e-5。

以下是我的代码:

#define SMALL 1e-5
//Double that attains this is considered non zero. Strictly Less than this is 0

int check_if_integer(double arg){
//returns 1 if arg is close enough to an integer
//returns 0 otherwise
    if(arg - (int)arg >= SMALL){
        if(arg + SMALL > (int)(arg+1.0)){
            return(1);
//Code should have reached this point since
//arg + SMALL is 16.00001 
//while (int)(arg+1.0) should be 16
//But the code seems to evaluate (int)(arg+1.0) to be 17
        }
    }
    else{
        return(1);
    }
    return(0);
}

int main(void){

    int a = check_if_integer(15.999999999999998);

}

不幸的是,在传递参数15.999999999999998时,函数返回0.也就是说,它认为参数是小数,而它应该返回1表示参数是"足够接近"到16岁。

我正在使用VS2010专业版。

任何指针都将非常感谢!

2 个答案:

答案 0 :(得分:2)

是的,浮点很难。仅仅因为15.999999999999998 < 16.0,这并不意味着15.999999999999998 + 1.0 < 17.0。假设您有一个三位精度的十进制浮点类型。对于9.99 + 1.0,该类型的精度会得到什么结果?数学结果为10.99,并四舍五入到该类型的精度给出11.0。二进制浮点具有相同的问题。

在这种特殊情况下,您可以将(int)(arg+1.0)更改为(int)arg+1(int)arg是准确的,整数加法也是如此。

答案 1 :(得分:2)

继hvd对类型的回答;由于它们在内部表示的方式,因此不建议在大型双打中加/减小双打。

一个简单的工作可以避免这两个问题:

if (abs(arg - round(arg)) <= SMALL) {
  return (1);
} else {
  return (0);
}