C 与Linux相比,Windows/MSYS2上的双重初始化错误

C 与Linux相比,Windows/MSYS2上的双重初始化错误,c,linux,gcc,msys2,C,Linux,Gcc,Msys2,这个简单的程序在Windows/MSYS2上给出了错误的结果。在Ubuntu 18.04上,它可以正常工作: #包括 #包括 int main(int argc,char*argv[]){ 双a=-1.5708; 双c=cos(-1.5708); 双d=cos(a); 无符号长*lc=(无符号长*)&c; 无符号长*ld=(无符号长*)&d; printf(“c=%.17e%llu\n”,c,*lc); printf(“d=%.17e%llu\n”,d,*ld); 如果(c==d) printf

这个简单的程序在Windows/MSYS2上给出了错误的结果。在Ubuntu 18.04上,它可以正常工作:

#包括
#包括
int main(int argc,char*argv[]){
双a=-1.5708;
双c=cos(-1.5708);
双d=cos(a);
无符号长*lc=(无符号长*)&c;
无符号长*ld=(无符号长*)&d;
printf(“c=%.17e%llu\n”,c,*lc);
printf(“d=%.17e%llu\n”,d,*ld);
如果(c==d)
printf(“正确结果\n”);
其他的
printf(“错误结果\n”);
返回0;
}
Windows/MSYS2:

$ gcc cos.c -o cos -lm ; ./cos
c = -3.67320510334657393e-06 13749155573439758092
d = -3.67320510334657563e-06 13749155573439758096
wrong result
Ubuntu 18.04:

olivier@ubuntu:~$ gcc cos.c -o cos -lm ; ./cos
c = -3.67320510334657393e-06 13749155573439758092
d = -3.67320510334657393e-06 13749155573439758092
correct result

我做错了什么,这是MSYS2上的gcc错误还是其他错误?

除了跨系统的
sqrt
之外,不能期望浮点函数得到相同的位结果

更具体地说,
cos
不能保证正确四舍五入,因此运行时库的结果(第二个结果
d
)不一定与编译期间发生的常量折叠的结果相同(结果
c

例如,上的页面指出,在不断折叠期间,所有操作都正确舍入(即使是超越函数),但由于效率原因,运行时库通常不是这样。(而且,并非所有编译器都会为您提供这种正确的四舍五入保证,以实现不断折叠,因此对于交叉编译器或使用不同于生成的可执行文件的libm的编译器,您可能会看到这个问题。)

GCC在内部使用MPFR库,该库使用中间任意精度算法实现正确的舍入操作,但在运行时库中,这将太慢

即使对于linux,您也可能会发现对
cos
函数的修改,从而导致
c
d
之间存在分歧(除非他们在后台使用crlibm)。因此,在我看来,linux的
c
d
结果是一致的


如果您在运行时寻找更可预测的FP数学结果,您可以签出,这是许多浮点函数的有效实现,可以提供正确的四舍五入结果。它比MPFR更有效,但不如标准的libm函数有效。

可能相关:使用
gcc-msse2-mfpmath=sse在Win7上用MinGW确认…
提供正确的输出。使用
gcc cos.c-msse2-mfpmath=sse-o cos-lm在带有gcc 64位的MSYS2上对我有效。