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)
为什么输出不同?与编译器有关吗?
与编译器有关吗?
是的,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)