c语言中,printf中%g的小数位数等于0.5,且长度大于6时,不是上位元,为什么?

Hel*_*ase 1 c printf gcc visual-studio-2010 visual-studio

这是我的程序:

#include <stdio.h>

int main()
{
    printf("%g\n", 100000.5);
    printf("%g\n", 100001.5);
    printf("%g\n", 100002.5);
    printf("%g\n", 100003.5);
    printf("%g\n", 100004.5);
    printf("%g\n", 100005.5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我使用gcc得到这个输出:

100000  
100002  
100002  
100004   
100004  
100006
Run Code Online (Sandbox Code Playgroud)

在 VS2019 中,我得到不同的输出,看起来更一致:

100001  
100002  
100003  
100004   
100005  
100006
Run Code Online (Sandbox Code Playgroud)

为什么输出不同?与编译器有关吗?

Dav*_*eri 5

与编译器有关吗?

是的,IEEE 754 定义了四种可能的舍入模式,引用自gcc 手册页

四舍五入到最接近的值。这是默认模式。除非有其他其中之一的特定需要,否则应使用它。在此模式下,结果将四舍五入到最接近的可表示值。如果结果介于两个可表示值之间,则选择偶数可表示值。即使在这里也意味着最低位为零。这种舍入模式可防止统计偏差并保证数值稳定性:冗长计算中的舍入误差将保持小于 FLT_EPSILON 的一半。

朝正无穷方向舍入。所有结果均四舍五入为大于结果的最小可表示值。

向负无穷大舍入。所有结果均四舍五入为小于结果的最大可表示值。

向零舍入。所有结果均四舍五入为最大可表示值,其大小小于结果的大小。换句话说,如果结果为负数,则向上舍入;如果为正,则向下舍入。

因此,gcc 使用“舍入到最接近的值”,而 Visual Studio 使用“舍入到正无穷大”

好消息是您可以更改模式:

fenv.h 定义了可用于引用各种舍入模式的常量。当且仅当 FPU 支持相应的舍入模式时,才会定义每一个。

在你的情况下:

#include <stdio.h>
#include <fenv.h>
                                                                                                                                             
int main(void)
{
    fesetround(FE_UPWARD);
    printf("%g\n", 100000.5);
    printf("%g\n", 100001.5);
    printf("%g\n", 100002.5);
    printf("%g\n", 100003.5);
    printf("%g\n", 100004.5);
    printf("%g\n", 100005.5);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)