浮点比较 C 的差异

h4c*_*k3d 0 c floating-point

float a = 0.7;
if(a<0.7)
  printf("true");
else
  printf("false");
Run Code Online (Sandbox Code Playgroud)

OUTPUT : true

现在,如果我将 a 的值更改为 1.7,那么

float a = 1.7;
if(a<1.7)
  printf("true");
else
  printf("false");
Run Code Online (Sandbox Code Playgroud)

OUTPUT : false

由于 0.7 被视为 double (HIGH PRECISION) 而 a 是浮点数 (LESS PRECISION),因此 a < 0.7 ,在第二种情况下它应该再次相同,因此它也应该打印 true。为什么这里的输出不同?

PS:我已经看过这个链接了。

Ste*_*non 5

既然您看到了对您链接的问题的回答,那么让我们解决它并进行必要的更改以检查您的第二个场景:


在二进制中,1.7 是:

b1.1011001100110011001100110011001100110011001100110011001100110...
Run Code Online (Sandbox Code Playgroud)

但是,1.7 是双精度文字,其值是 1.7 舍入到最接近的可表示双精度值,即:

b1.1011001100110011001100110011001100110011001100110011
Run Code Online (Sandbox Code Playgroud)

在十进制中,这正是:

 1.6999999999999999555910790149937383830547332763671875
Run Code Online (Sandbox Code Playgroud)

当您写入 float a = 1.7 时,该 double 值将再次舍入为单精度,并且 a 获取二进制值:

b1.10110011001100110011010
Run Code Online (Sandbox Code Playgroud)

这正是

 1.7000000476837158
Run Code Online (Sandbox Code Playgroud)

十进制(注意它四舍五入!)

当您进行比较 (a < 1.7) 时,您是在将这个单精度值(转换为 double,它不会四舍五入,因为所有单精度值都可以用双精度表示)与原始双精度值进行比较。因为

 1.7000000476837158 > 1.6999999999999999555910790149937383830547332763671875
Run Code Online (Sandbox Code Playgroud)

比较正确返回false,并且您的程序打印“false”。


好的,那么为什么 0.7 和 1.7 的结果不同呢?这一切都在四舍五入中。单精度数有 24 位。当我们用二进制写下 0.7 时,它看起来像这样:

b.101100110011001100110011 00110011...
Run Code Online (Sandbox Code Playgroud)

(第 24 位后有空格显示它的位置)。因为第 24 位之后的下一个数字是零,所以当我们四舍五入到 24 位时,我们向下舍入。

现在看 1.7:

b1.10110011001100110011001 10011001...
Run Code Online (Sandbox Code Playgroud)

因为我们有前导1.,第 24 位的位置发生了变化,现在第 24 位之后的下一个数字是 1,我们改为向上取整。