C++ 64位和32位体系结构之间的atan2结果不一致

C++ 64位和32位体系结构之间的atan2结果不一致,c++,gcc,x86,floating-point,precision,C++,Gcc,X86,Floating Point,Precision,使用std::atan2时,我会得到不同的结果,这取决于我是否交叉编译32位体系结构,而不是编译(本机)64位体系结构 $cat test.cc #包括 #包括 int main(int argc,字符**argv){ printf(“%f\n”,标准::atan2(366.470947f,-116.213623f)); } $gcc test.cc-o test-lm-ffp contract=off-fflot store 美元/测试 1.877880 $gcc-m32 test.cc-o

使用
std::atan2
时,我会得到不同的结果,这取决于我是否交叉编译32位体系结构,而不是编译(本机)64位体系结构

$cat test.cc
#包括
#包括
int main(int argc,字符**argv){
printf(“%f\n”,标准::atan2(366.470947f,-116.213623f));
}
$gcc test.cc-o test-lm-ffp contract=off-fflot store
美元/测试
1.877880
$gcc-m32 test.cc-o test-lm-ffp contract=off-fflot store
美元/测试
1.877881
我希望结果是一样的,因为我正在将应用程序移植到64位,并且需要相同的浮点结果。如您所见,我已经尝试过
-ffp contract=off-ffloat store
,我知道这可能会导致浮点不一致。我还缺什么吗?还是说触发功能没有以这种方式标准化


我运行的是Ubuntu 18.04.2和gcc 7.5.0。CPU是一款i7-1065G7。

不幸的是,您遇到了一个长期存在的gcc错误变体:

问题是GCC在不同的情况下会或不会使用80位FP精度,我们约束它的能力是有限的

使用
-m32
强制gcc生成将在i386上运行的代码,因此别无选择,只能使用80位扩展精度FPU指令。原则上,您可以对32位内存模型使用
-mx32
,但如果您的运行时环境满意,则可以使用x86-64

但你还是会有麻烦的:

  • -m32
    将调用标准库版本的
    atan2
    ,该版本从387 FP堆栈中提取参数,与使用xmm寄存器传递参数的实现不同
  • 通过优化,GCC将使用扩展的双精度评估在编译时计算结果。因此,例如使用
    -O3
    ,您将获得1.877881,同时使用
    -m32
    -m64
    ,这两个值都与您将从32位浮点计算中获得的值不一致
  • 选项>代码> f过剩精度=标准< /COD>——它保证避免这种更高精度的评估-只在C中工作,而不是C++。见:

简而言之,这种情况非常不令人满意,已经持续了二十多年。

Re:
我需要相同的浮点结果
-你会过得很不愉快的。谢谢你的链接。我似乎也在遭受同样的痛苦(不确定我在搜索中怎么会错过它)。是的,如果不能保证一致性,听起来像是坏消息。这是否回答了你的问题?是时候切换到重复的叮当声了:,…谢谢你的详细回答。我能编写C中受影响的数学函数的包装器,用<代码> -fOfTime=标准< /C> >编译,并将这些链接到我的C++程序中吗?幸运的是,我能够改变C++代码中的函数调用来引用我的包装版本,所以这是一个不错的解决方案。另一种选择是编写自己的超越函数(或使用其他人的函数)。这样可以避免编译时优化问题,然后您可以选择一个尽可能精确的实现,或者使用矢量化等。但这显然不是一个容易的选择:)
$ cat test.cc 
#include <cmath>
#include <stdio.h>

int main(int argc, char **argv) {
    printf("%f\n", std::atan2(366.470947f, -116.213623f));
}

$ gcc test.cc -o test -lm -ffp-contract=off -ffloat-store
$ ./test 
1.877880
$ gcc -m32 test.cc -o test -lm -ffp-contract=off -ffloat-store
$ ./test 
1.877881