Jer*_*son 2 c floating-point gcc gcc4.8
使用 gcc 4.8.2 (Ubuntu 14.04) 我得到不同的结果,同时基本上以相同的方式计算一个值。根据我测试的系统上的架构(32 位 / 64 位),也存在差异。
#include <math.h>
#include <stdio.h>
int main()
{
float h = 0.11f;
float y = 0.11f;
float g = 1.37906f;
float x = 2.916949f;
float result1 = (h * y / fabs(g)) / x;
float result2 = h * y / fabs(g);
result2 /= x;
float result3 = (h * y / g) / x;
printf("%.20f \n", result1); //0.00300796888768672943
printf("%.20f \n", result2); //0.00300796912051737309
printf("%.20f \n", result3); //0.00300796912051737309 on x64
//0.00300796888768672943 on x32
}
Run Code Online (Sandbox Code Playgroud)
这是什么原因,我如何预测或避免这些差异?
编辑:将晶圆厂投射到浮动不会改变结果,至少在我的系统上(见 Oli Charlesworth 的评论)。
C99 标准并没有像早期的 Java 标准那样强制所有 C 编译器为浮点计算实现严格的标准,而是允许相对于理想模式进行一些变化,在这种模式下,每个操作都按照相应的 IEEE 754 格式按顺序完成并舍入。到浮点类型。
您可以询问 GCC 它遵循什么浮点计算模型,并且您可以使用命令行选项来更改其行为并使其更具可预测性。有两种情况:
-std=c99. 没有它(特别是,没有-fexcess-precision=standard它暗示),浮点计算的确切结果是不可预测的,并且您允许编译器为result1、result2和生成不同的结果result3。用-std=c99,的值result1和result3必须相同。的值result2可能不同,因为中间分配 toresult2强制计算该点处的值四舍五入为 a float。-msse2 -mfpmath=sse)。在这种模式下,fabs被替换的所有三个计算都fabsf应该产生相同的结果。这具有生成仅与过去 12 年左右生产的处理器兼容的代码的缺点(!)更多信息:post1 , post2,从打算为 C 程序编写静态分析器的人的角度编写,该分析器可精确预测浮点计算的结果。