C++ 处理过高的精度

标签 c++ gcc floating-point floating-point-precision extended-precision

我目前正在查看 code which does multi-precision floating-point arithmetic .为了正常工作,该代码需要在明确定义的点将值降低到最终精度。因此,即使中间结果计算为 80 bit extended precision浮点寄存器,在某些时候它必须四舍五入为 64 bit double用于后续操作。

代码中使用宏INEXACT来描述这个需求,但没有一个完美的定义。 gcc manual提到 -fexcess-precision=standard 作为强制强制转换和赋值操作定义明确的精度的方法。然而,它也写道:

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

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

我想对于我当前的用例,我可能会在任何情况下使用 -mfpmath=sse,据我所知,这不会导致任何过高的精度。但我还是很好奇。

最佳答案

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

C99 标准定义了 FLT_EVAL_METHOD,这是一个编译器设置的宏,它定义了 C 程序中应该如何发生超精度(许多 C 编译器的行为方式仍然不完全符合最合理的他们定义的 FP_EVAL_METHOD 的值的解释:生成 387 代码的旧 GCC 版本,生成 387 代码时的 Clang,...)。 C11 标准阐明了与 FLT_EVAL_METHOD 的效果相关的细微之处。

自 2011 年标准以来,C++ defers to C99 FLT_EVAL_METHOD 的定义(header cfloat)。

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


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.

这是通常的解决方案。

请注意,C99 还在 math.h 中定义了 FP_CONTRACT,您可能想要查看:它与以更高的精度计算某些表达式的相同问题有关,从完全不同的side(现代融合乘加指令而不是旧的 387 指令集)。这是一个 pragma,用于决定是否允许编译器用 FMA 指令替换源代码级加法和乘法(这具有乘法实际上以无限精度计算的效果,因为这就是该指令的工作方式,而不是四舍五入为类型的精度,就像单独的乘法和加法指令一样)。这个 pragma 显然没有被纳入 C++ 标准(据我所知)。

此选项的默认值是实现定义的,有些人认为默认值是允许生成 FMA 指令(对于将 FLT_EVAL_METHOD 定义为 0 的 C 编译器)。 你应该,在 C 中,面向 future 你的代码:

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

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


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

恐怕这个问题的答案是 GCC 的行为,比如说,在生成 387 代码时,是荒谬的。请参阅 situation 的说明这促使 Joseph Myers 解决了 C 的问题。如果 g++ 没有实现 -fexcess-precision=standard,这可能意味着 80 位计算被随机舍入到类型的精度,当编译器碰巧不得不将一些浮点寄存器溢出到内存中,导致下面的程序在程序员无法控制的某些情况下打印“foo”:

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

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

关于C++ 处理过高的精度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20869904/

相关文章:

c++ - std::atomic 与另一个字符 union

c++ - 用非常量变量声明数组大小

Python:返回最大 float 而不是 infs?

c++ - 输出未按正确顺序打印

c++ - CRC16 modbus 计算为长数据包返回错误值

c++ - 使用 Cygwin + gcc 编译 Boost 示例项目

c - C 中迭代次数少的段错误

gcc - 禁用-msse

pandas - 用pandas.to_excel将float值截断到小数点后8位

rust - 如何在不进行手动解析的情况下从可能包含剩余字符的字符串中解析 float ?