C ++处理超额精度 [英] C++ handling of excess precision

查看:394
本文介绍了C ++处理超额精度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在查看执行多精度浮动的代码点算术。为了正确地工作,该代码需要将值在精确定义的点处降低到其最终精度。因此,即使中间结果计算为 80位扩展精度浮点寄存器,在某些时候它也必须则舍入为 64位double 用于后续操作。

I'm currently looking at code which does multi-precision floating-point arithmetic. To work correctly, that code requires values to be reduced to their final precision at well-defined points. So even if an intermediate result was computed to an 80 bit extended precision floating point register, at some point it has to be rounded to 64 bit double for subsequent operations.

代码使用宏 INEXACT 描述此要求,但没有完美的定义。 gcc手动提及 -fexcess-precision = standard 作为强制转换和赋值操作的精确定义的精度的一种方法。然而,它还写道:

The code uses a macro INEXACT to describe this requirement, but doesn't have a perfect definition. The gcc manual mentions -fexcess-precision=standard as a way to force well-defined precision for cast and assignment operations. However, it also writes:


' - fexcess-precision = standard' $ b

‘-fexcess-precision=standard’ is not implemented for languages other than C

现在我正在考虑将这些想法移植到C ++(如果有人知道现有的实现,欢迎评论)。所以看来我不能使用这个开关的C ++。 但是没有任何开关的g ++默认行为是什么?有没有更多的C ++类似的方法来控制超额精度的处理?

Now I'm thinking about porting those ideas to C++ (comments welcome if anyone knows an existing implementation). So it seems I can't use that switch for C++. But what is the g++ default behavior in absence of any switch? Are there more C++-like ways to control the handling of excess precision?

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

I guess that for my current use case, I'll probably use -mfpmath=sse in any case, which should not incur any excess precision as far as I know. But I'm still curious.

推荐答案


有更多的C ++控制处理方式的超额精度?

Are there more C++-like ways to control the handling of excess precision?

C99标准定义了 FLT_EVAL_METHOD 宏,它定义了在C程序中超额精度的发生情况(许多C编译器的行为方式不完全符合 FP_EVAL_METHOD 的值的最合理解释他们定义:旧的GCC版本生成387代码,ang当生成387代码,...)。

The C99 standard defines FLT_EVAL_METHOD, a compiler-set macro that defines how excess precision should happen in a C program (many C compilers still behave in a way that does not exactly conform to the most reasonable interpretation of the value of FP_EVAL_METHOD that they define: older GCC versions generating 387 code, Clang when generating 387 code, …). Subtle points in relation with the effects of FLT_EVAL_METHOD were clarified in the C11 standard.

自2011年的标准以来,C ++标准已经在C11标准中明确了 FLT_EVAL_METHOD 延迟到C99 定义 FLT_EVAL_METHOD (header cfloat)。

Since the 2011 standard, C++ defers to C99 for the definition of FLT_EVAL_METHOD (header cfloat).

所以GCC应该简单地允许 -fexcess-precision = standard 对于C ++,希望它最终会。与C语言相同的语义已经在C ++标准中,它们只需要在C ++编译器中实现。

So GCC should simply allow -fexcess-precision=standard for C++, and hopefully it eventually will. The same semantics as that of C are already in the C++ standard, they only need to be implemented in C++ compilers.


我想,对于我目前的用例,我可能会在任何情况下使用-mfpmath = sse,这不应该产生任何超额的精度,就我所知。

I guess that for my current use case, I'll probably use -mfpmath=sse in any case, which should not incur any excess precision as far as I know.

这是通常的解决方案。

That is the usual solution.

请注意,C99还在math.h中定义了 FP_CONTRACT ,您可能需要查看:一些表达式以相同的问题以更高的精度计算,从完全不同的一侧(现代的融合乘法 - 加法指令而不是旧的387指令集)触发。这是一个编译指令,决定编译器是否允许用FMA指令替换源级添加和乘法(这样做的结果是乘法是以无限精度虚拟计算的,因为这是该指令的工作原理,而不是四舍五入到类型的精度,因为它将与单独的乘法和加法指令)。这个pragma显然没有被纳入C ++标准(就我所见)。

Be aware that C99 also defines FP_CONTRACT in math.h that you may want to look at: it relates to the same problem of some expressions being computed at a higher precision, striking from a completely different side (the modern fused-multiply-add instruction instead of the old 387 instruction set). This is a pragma to decide whether the compiler is allowed to replace source-level additions and multiplications with FMA instructions (this has the effect that the multiplication is virtually computed at infinite precision, because this is how this instruction works, instead of being rounded to the precision of the type as it would be with separate multiplication and addition instructions). This pragma has apparently not been incorporated in the C++ standard (as far as I can see).

这个选项的默认值是实现定义的,有些人认为默认为允许生成FMA指令(对于否则定义 FLT_EVAL_METHOD 为0的C编译器)。
你应该在C中保证未来的
你的代码与:

The default value for this option is implementation-defined and some people argue for the default to be to allow FMA instructions to be generated (for C compilers that otherwise define FLT_EVAL_METHOD as 0). You should, in C, future-proof your code with:

#include <math.h>
#pragma STDC FP_CONTRACT off

如果你的编译器提供了一个文档,

And the equivalent incantation in C++ if your compiler documents one.


缺少任何开关时的g ++默认行为是什么?

what is the g++ default behavior in absence of any switch?

我恐怕这个问题的答案是GCC的行为,比如说,在生成387代码时,是无意义的。请参阅情况的说明,该动作促使约瑟夫·迈尔斯修复C的情况。如果g ++没有实现 -fexcess-precision = standard ,它可能意味着80位计算随机舍入到类型的精度编译器偶尔必须将一些浮点寄存器溢出到内存,导致程序下面的程序在程序员控制之外打印foo:

I am afraid that the answer to this question is that GCC's behavior, say, when generating 387 code, is nonsensical. See the description of the situation that motivated Joseph Myers to fix the situation for C. If g++ does not implement -fexcess-precision=standard, it probably means that 80-bit computations are randomly rounded to the precision of the type when the compiler happened to have to spill some floating-point registers to memory, leading the program below to print "foo" in some circumstances outside the programmer's control:

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

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

… because the code in the ellipsis caused x, that was held in an 80-bit floating-point register, to be spilt to a 64-bit slot on the stack.

这篇关于C ++处理超额精度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆