c - 为什么 GCC 在添加浮点值时会给出意想不到的结果?

标签 c gcc floating-point

我正在使用 GCC 编译一个添加 float 、长整型、整数和字符的程序。当它运行时,结果很糟糕。以下程序意外打印出值 34032.101562。

使用 Microsoft 编译器重新编译会给出正确的结果。

#include <stdio.h>

int main (void) {
    const char val_c = 10;
    const int val_i = 20;
    const long val_l = 34000;
    const float val_f = 2.1;

    float result;
    result = val_c + val_i + val_l + val_f;

    printf("%f\n", result);
    return 0;
}

最佳答案

你认为“正确的结果”是什么?我猜你认为它是 34032.1。它不是。

2.1 不能表示为 float,因此 val_f 改为使用最接近的可表示 float 值进行初始化。在二进制中,2.1 是:

10.000110011001100110011001100110011001100110011001...

float 有 24 个二进制数字,所以 val_f 的二进制值为:

10.0001100110011001100110

表达式 resultat = val_c + val_i + val_l + val_f 计算 34030 + val_f,它以单精度计算并导致另一次舍入。

  1000010011101110.0
+               10.0001100110011001100110
-----------------------------------------
  1000010011110000.0001100110011001100110
rounds to 24 digits:
-----------------------------------------
  1000010011110000.00011010

用十进制表示,这个结果正好是 34032.1015625。因为 %f 格式在小数点后打印 6 位数字(除非另有说明),这再次四舍五入,并且 printf 打印 34032.101562

现在,为什么用 MSVC 编译时得不到这个结果?如果编译器选择这样做,C 和 C++ 标准允许以更广泛的类型执行浮点计算。 MSVC 在您的计算中执行此操作,这意味着 34030 + val_f 的结果在传递给 printf 之前不会四舍五入。在这种情况下,打印的精确浮点值是 34032.099999999991268850862979888916015625,由 printf 四舍五入为 34032.1。

为什么不是所有的编译器都做 MSVC 所做的事情?几个原因。首先,它在某些处理器上速度较慢。其次,更重要的是,虽然它可以给出更准确的答案,但程序员不能依赖于此——看似无关的代码更改可能会导致答案在这种行为存在的情况下发生变化。正因为如此,携带额外的精度通常会导致比它解决的问题更多的问题。

关于c - 为什么 GCC 在添加浮点值时会给出意想不到的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6794398/

相关文章:

c - 如何处理高位数字的计算?

c - 当结构中的整数后跟大小大于整数的字符时,填充不会应用于该整数

gcc - CMake链接共享库-找不到lOgreMain

c - 释放结构内部的指针(指向 void*)

gcc - __attribute__ vector_size(16) 是什么意思?

c - 运算符 ':=' 是什么意思?

将浮点文字转换为 x86 程序集中的 int 表示形式?

python - 将 python float 写入文件时抑制科学记数法

c - 进程的退出状态如何取决于它是否是静态构建的?

c - 理解c中的语法难题