C++处理过多的精度

MvG*_*MvG 11 c++ floating-point gcc floating-point-precision extended-precision

我目前正在研究进行多精度浮点运算的代码.为了正常工作,该代码要求在明确定义的点处将值降低到最终精度.因此,即使将中间结果计算到80位扩展精度浮点寄存器,在某些时候也必须将其四舍五入为后续操作的64位双精度.

代码使用宏INEXACT来描述此要求,但没有完美的定义.在GCC手册中提到-fexcess-precision=standard的办法迫使流延和赋值操作定义良好的精度.但是,它还写道:

对于C以外的语言,未实现"-fexcess-precision = standard"

现在我正在考虑将这些想法移植到C++(如果有人知道现有的实现,则欢迎评论).所以我似乎无法将该开关用于C++.但是没有任何开关的g ++默认行为是什么?是否有更多类似C++的方法来控制过度精度的处理?

我想对于我目前的用例,我可能会-mfpmath=sse在任何情况下使用,据我所知,这不应该产生任何过多的精度.但我仍然很好奇.

Pas*_*uoq 5

还有更多类似C ++的方法来控制超精度处理吗?

C99标准定义FLT_EVAL_METHOD了一个编译器集宏,该宏定义了C程序中应如何进行超精度处理(许多C编译器的行为仍不完全符合对其FP_EVAL_METHOD定义值的最合理解释:较早的GCC生成387代码的版本,生成387代码时的Clang,…)。与FLT_EVAL_METHODC11 效果有关的细微之处已在C11标准中阐明。

从2011年标准开始,C ++ 遵循(header cfloat)的定义遵循C99FLT_EVAL_METHOD

因此,GCC应该只允许-fexcess-precision=standard使用C ++,并希望最终可以使用。C ++标准中已经具有与C相同的语义,只需要在C ++编译器中实现即可。


我想对于我当前的用例,在任何情况下我都可能会使用-mfpmath = sse,就我所知,这不会引起任何额外的精度。

那是通常的解决方案。

请注意,C99 FP_CONTRACT在math.h中也定义了您可能要看的:它涉及到以下问题:以更高的精度计算某些表达式,而这又是完全不同的一面(相反,现代的熔融-乘法-加法指令旧387指令集)。决定是否允许编译器使用FMA指令替换源代码级的加法和乘法是一个务实的做法(这导致乘法运算实际上以无限精度进行计算,因为这是该指令的工作方式,而不是四舍五入为类型的精度,就像使用单独的乘法和加法指令一样)。据我所知,这种杂用显然没有被并入C ++标准。

此选项的默认值是实现定义的,有人认为默认值是允许生成FMA指令(对于C编译器,否则定义FLT_EVAL_METHOD为0)。在C语言中,您应该使用以下方法对代码进行过时验证:

#include <math.h>
#pragma STDC FP_CONTRACT off
Run Code Online (Sandbox Code Playgroud)

如果您的编译器记录了一个,那么C ++中的等效咒语。


没有任何切换时,g ++的默认行为是什么?

恐怕这个问题的答案是,海湾合作委员会的行为,例如在生成387代码时,是荒谬的。见的描述的情况是积极约瑟夫·迈尔斯定为C.如果克情况++没有实现-fexcess-precision=standard,这可能意味着80位计算随机四舍五入至类型的精度时,编译器碰巧有洒一些浮动点寄存器到内存中,导致下面的程序在程序员无法控制的某些情况下打印“ foo”:

if (x == 0.0) return;
... // code that does not modify x
if (x == 0.0) printf("foo\n");
Run Code Online (Sandbox Code Playgroud)

…因为省略号中的代码导致x保留在80位浮点寄存器中的代码溢出到堆栈上的64位插槽中。