为什么 printf("%.3f\n", 123456.987654) 打印 123456.984?

Why does printf("%.3f\n", 123456.987654) print 123456.984?

为什么下面的 printf 打印出 123456.984 而不是 123456.988?

#include <stdio.h>
int main()
{
    printf("%.3f\n", 123456.987654);
    return 0;
}

编辑:我弄错了,正确的printf是:

printf("%.3f\n", 123456.987654f);

该错误肯定与浮点精度有关。它可以用 float 常量复制。

使用浮点常量执行此 printf() 会显示您描述的行为。但是,如果您传递双精度常量,则结果如预期的那样:

#include <stdio.h>
int main()
{
    printf("%.3f\n", 123456.987654f);  // float: insufficient precision .984
    printf("%.3f\n", 123456.987654);   // double: better precision .988
                    // unsuffixed floating point constants are double
    return 0;
}

Online demo

这是由于在转换回十进制时 floating point numbers, that use power of two and fractions of power of twos to represent the numbers. The closest representation corresponding to a number might not be close enough 的内部表示中的近似值。

这种奇怪的舍入行为取决于实现:C 标准没有指定必须使用哪种浮点表示法。

你使用的编译器肯定是基于IEEE 754 standard. On this great web page的,你可以验证一个选定的浮点数是如何使用IEEE单精度编码的:对于123456.987654,几乎使用了所有的位和最接近的位可以用单精度表示的数字是 123456.984375。

在我的电脑上打印出下面的程序(用 gcc 编译)

123456.988
123456.988
123456.984

您问题中的代码实际上是在显示问题,还是涉及到浮动?如果有一个浮点数,那么问题是一个浮点数只有大约 7 个数字的精度。当打印到小数点后 3 位时,最接近您的数字的浮点数约为 123456.984

#include    <stdio.h>
#include    <stdlib.h>

    int main( void)
    {
        printf("%.3f\n", 123456.987654);
        double  d = 123456.987654;
        printf("%.3f\n", d);
        float   f = 123456.987654;
        printf("%.3f\n", f);
        return EXIT_SUCCESS;
    }

您遇到的问题似乎是 implementation/compiler-specific(甚至可能与编译或执行有关)。这对我来说是不可复制的。

在在线 Godbolt 编译器和执行器上使用 gcc 9.1 版和 clang 9.0 版,两者的输出都是 123456.988

这里是 Link.