(0.1 + 0.2) == 0.3 是真还是假?

1 c floating-point bit-manipulation

我对浮点数有基本的了解,并且正在阅读这篇文章,其中说:

0.1 + 0.2:这等于 0.3,但在浮点中:(0.1 + 0.2) == 0.3是假的。这是因为 0.1、0.2 和 0.3 不能用基数 2 浮点数精确表示。

嗯,根据浮点数的性质确实是这样,不过我写了一个简单的程序来测试:

float a = 0.1;
float b = 0.2;

if(a+b == 0.3)
{
  printf("true");
} else 
{
  printf("false");
}
// result is true
Run Code Online (Sandbox Code Playgroud)

但输出实际上是true. 这是我的两个问题:

  1. 我想发生的事情是,因为C使用了舍入到偶数的舍入模式,所以舍入后,它恰好是真的,我的理解是否正确?

  2. 如果我的理解是正确的,那么在这种情况下一定有一些指定的浮点数不会为真,因为舍入失败的可能性仍然很小。所以这必须是某种组合

    float a = ...;
    float b = ...;
    if(a+b == XXX)  // where XXX is the "intuitive" sum of a and b
    {
      printf("true");
    } else 
    {
      printf("false");   
    }
    
    //result is false now
    
    Run Code Online (Sandbox Code Playgroud)

我的理解正确吗?

T.J*_*der 7

我得到false你的程序,而不是true你在你的问题中指出的。(0.3是一个double文字,所以我的猜测是,当您在本地测试时,您使用的是一个float变量而不是0.3文字。) 如果您实际使用float(== 0.3f而不是== 0.3),您将获得true作为输出,因为恰好与float,0.1 + 0.2 == 0.3为真.

但是,基本点仍然是(单精度)和(双精度)使用的IEEE-754 二进制浮点计算速度非常快并且对很多事情有用,但对于某些值来说本质上是不精确的,所以你得到这样的问题。有了,你得到的,但你得到的:floatdoublefloattrue0.1 + 0.2 == 0.3false0.1 + 0.6 == 0.7

#include <stdio.h>

int main() {
    printf("%s\n", 0.1f + 0.6f == 0.7f ? "true" : "false"); // prints false
    //             ^^^^???^^^^????^^^^??? `float` literals
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

0.1 + 0.2 == 0.3这个问题的著名版本恰好是double

#include <stdio.h>

int main() {
    printf("%s\n", 0.1 + 0.2 == 0.3 ? "true" : "false"); // prints false
    //             ^^^???^^^????^^^??? `double` literals
    return 0;
}
Run Code Online (Sandbox Code Playgroud)