如何让GCC(C++)停止简化算术表达式?

问题描述 投票:2回答:1

我正在做一个物理引擎,为了好玩.我试图使它可靠,即使在低tickrates,所以我做了一个危险的舞蹈与浮点算术和精度。

在调试的时候,我最终运行了这段代码。

#define A 0.2063387632369995100000000000000f
#define B 0.7307806611061096200000000000000f


float a = A;
float b = B;

float floatie1 = A + (B * ((A)/(-B)));
float floatie2 = a + (b * ((a)/(-b)));
printf("%.40f\n", floatie1);
printf("%.40f\n", floatie2);

输出结果是:

0.0000000149011611938476560000000000000000
0.0000000000000000000000000000000000000000

以及每个比特的位数(分别):

00110010100000000000000000000000
00000000000000000000000000000000

我知道这个表达式应该是计算为0 但我不想让它计算为0 因为我可能在代码中的某个地方有其他不相关的运算 会给我一个完全相同的不精确的值 如果我再减去2,它就会变成0 我不希望我的表达式在任意情况下被简化或优化

我试过让浮点数变得不稳定,并关闭优化,但无济于事。我也试过 -f-associative-math, -ftrapping-math-funsafe-math-optimizations的组合,以及它们的 no- 变体。

如果我把表达式拆开,把东西放到不同的变量中,一次只做一件事,就可以了,但我不想每次写一段代码都要在背后看。

MSVC++给我的这段代码开箱即用的正确结果。

版本:Windows 8.1。gcc (MinGW.org GCC-6.3.0-1) 6.3.0 windows 8. 1. 如何关闭这个功能?

c++ gcc floating-point g++ precision
1个回答
1
投票

所有的功劳都归于 EOF.

我问错问题了。这不是真正的GCC简化表达式。

显然,GCC默认对32位进行了优化,使其使用更少的x87 FPU指令。尽管速度更快,但并不能保证符合IEEE 754的要求,因为在引擎盖下使用了双倍指令(EOF在他的 评论).

之所以结果不同,是因为GCC在编译时使用了符合IEEE 754标准的算子来计算第一个表达式的值,而对于第二个表达式(运行时),则使用了不符合标准的FPU指令。

为了避免这些指令(请记住这会使代码更慢),可以使用 -ffloat-store 作为编译选项。

或者,如果你不想让整个程序变得更慢,可以使用 杠杠 或函数属性。

void __attribute__((optimize ("-ffloat-store"))) func(float a, float b){
    //your code
}

:而不是 x87 FPU可以选择性地尝试将目标锁定在 上交所的扩展部分,它既符合IEEE 754标准,又是x86_64的基线。更多信息 此处.

© www.soinside.com 2019 - 2024. All rights reserved.