如果先前将double初始化为零,那么将double比较为零是正确的吗?

HAL*_*000 15 c c++ floating-point

我了解到比较双重使用==并不是明智的做法.但是我想知道检查双重是否已经初始化可能是危险的.例如,知道变量doubleVar如果已初始化则不能为零,这样做是否安全?

Foo::Foo(){
    doubleVar = 0.0;  // of type double
}

void Foo::Bar(){
    if(doubleVar == 0){ // has been initialized?
        //...
    }else{
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)

oua*_*uah 15

在IEEE-754中,长话短说:

double d;

d = 0.0;
d == 0.0   // guaranteed to evaluate to true, 0.0 can be represented exactly in double
Run Code Online (Sandbox Code Playgroud)

double d;

d = 0.1;
d == 0.1   // not guaranteed to evaluate to true
Run Code Online (Sandbox Code Playgroud)

  • 为什么后者*不能保证是真的?它是*相同的*值(根据需要应该通过相同的促销). (5认同)
  • 没人在做现实世界的节目!! 我的GCC编译器给出FALSE作为以下代码的返回:`double x = 0.1; return x == 0.1;`.这是正确的,因为在我的情况下常量`FLT_EVAL_METHOD`是2,这意味着每个常量和中间计算都是以'long double`精度完成的.例外情况是**演员和作业**.因此,`double`变量`x`,初始化为`0.1`,具有'double`精度值`0.1`,但常量本身`0.1`总是一个`long double`,所以comparisson必须是的,这确实发生了. (5认同)
  • @ HAL9000我认为*无关紧要*因为在*两个地方使用相同的值*因此在内部具有*相同的*位模式.这与涉及数学的"0.3 + 0.2 == 0.5"相反. (4认同)
  • @ouah:严格来说,在C中,两种情况*都应该*评估为真(6.4.4.2 p4"未填充的浮动常量具有类型double."和p7"浮动常量的转换时间转换应该与执行时转换相匹配库函数的字符串,例如strtod,给定适合两种转换的匹配输入,相同的结果格式,以及默认的执行时间舍入.")然而,这些问题确实存在,有点快速和松散的skanky编译器. (3认同)
  • @ HAL9000:如果你设置一个双精度到0.75并且它没有那个值,那就是非常非常错误的.0.75在生产中使用的每个浮点运算系统中都是完全可表示的.也许你的意思是一个通常不能代表0.6的值? (2认同)
  • @ user2864740:可能发生的是`0.1`从源文本转换为内部格式,精度高于`double`.然后,在`d = 0.1`中,此内部值转换为`double`,因为赋值需要使用指定对象的名义类型; 必须丢弃过高的精度.此转换可以产生不同的值.然后,在`d == 0.1`中,存储在`d`中的`double`及其改变的值与超精度的`0.1`进行比较.值不同,因此比较结果为false. (2认同)
  • 这个答案假定IEEE 754为了声称分配和比较零工作,但随后声称分配和与.1的比较可能不起作用.如果对两者都做出相同的假设,那么C实现以合理的方式绑定到IEEE 754,那么两者都有效.如果没有做出假设,那么C标准都不能保证.(C标准不保证源文本"0.0"被精确地转换为零.它可以转换为紧邻的值,例如,最小正"long double"值.) (2认同)