C 浮点异常处理

问题描述

fenv.hferaiseexcept 及其同类)的手册页异常缺乏信息;我在网上找到的例子(cppreference.com 和其他)非常少。

它们应该如何使用?特别是,feraiseexcept(...) 是否总是返回?从一个获取非法参数的函数中应该返回什么,比如 sqrt(-1)?我假设 NAN

应该在函数获取并恢复原始状态吗?例如,人们可能会为某个迭代算法计算一个起点,如果该计算结果不准确,则可以推测,迭代可以收敛到全精度。

应该如何在程序调用中使用它,例如库函数

(我宁愿不必深入研究随机数学库资源来回答上述问题。)

解决方法

fenv.hferaisexceptionand [它的] 同类)的手册页异常缺乏信息,我在网上(cppreference.com 和其他网站)上找到的示例非常少。

<fenv.h>the C standard 指定。 Unix 手册页仅在扩展 C 规范时才有用。对 cppreference.com 持怀疑态度;已知有错误。

应该如何使用它们?

讨论所有 <fenv.h> 对于 Stack Overflow 来说是一个过于宽泛的问题。

特别是,feraisexception(...) 是否总是返回?

根据 C 2018 7.6.2.3 2 和 foonote 221,feraiseexcept 试图引起浮点异常,就好像它们是由算术指令生成的一样。因此,如果它引发了一个启用了陷阱的异常,它将导致一个陷阱。

相比之下,fesetexceptflag 仅设置浮点异常标志,而不会生成实际异常。根据 7.6.2.4 2,“……此函数不会引发浮点异常,而只会设置标志的状态。”

从获取非法参数的函数(例如 sqrt(-1))应该返回什么?我假设 NAN

这在 <fenv.h> 的域之外。 sqrt 在 7.12 中指定,涵盖 <math.h>。根据 7.12.7.5 2,如果参数小于零,则会发生 sqrt 域错误。根据 7.12.1,2,“......在域错误时,函数返回一个实现定义的值......”并且它还可能设置 errno 和/或引发“无效”浮点异常。通常,实现会返回一个安静的 NaN。

是否应该在函数中获取并恢复原始状态?

这取决于指定或实现功能的人。提供“基本”数学函数的例程,对于标准数学库,可能只需要按照所提供的理想函数的要求影响浮点状态,隐藏任何内部操作。例如,如果 log10(100) 是通过使用工程多项式逼近对数来实现的,则多项式的计算可能使用具有非常高的精度和准确度的算术运算,如此之高以至于最终结果,当四舍五入到最终格式,正好是两个。但是中间计算可能涉及一些不准确的操作。因此,将引发不精确的异常。如果该例程仅计算多项式并返回准确结果 2,则会引发不准确标志。理想情况下,该例程将抑制浮点陷阱、保存异常标志、进行计算、恢复最初启用的陷阱、设置适当的异常标志(如果有)并返回结果。 (或者,可以实现该例程以仅使用整数算术,从而避免浮点问题。)

在专门的库例程之外,浮点子例程很少达到这种程度。这取决于每个应用程序希望其例程如何运行。

例如,人们可能会为某个迭代算法计算一个起点,如果该计算结果不准确,则没有相关性,因为迭代可以收敛到全精度。

这一段不清楚,可能不合语法。我无法按书面形式回答。

应该如何在程序调用中使用它,例如库函数?

这个问题不清楚,可能是因为上一段不够清楚。 “这个”的前因不明。