处理浮点exception

我不知道如何处理C或C ++中的浮点exception。 从wiki中,有以下类型的浮点exception:

IEEE 754 specifies five arithmetic errors that are to be recorded in "sticky bits" (by default; note that trapping and other alternatives are optional and, if provided, non-default). * inexact, set if the rounded (and returned) value is different from the mathematically exact result of the operation. * underflow, set if the rounded value is tiny (as specified in IEEE 754) and inexact (or maybe limited to if it has denormalisation loss, as per the 1984 version of IEEE 754), returning a subnormal value (including the zeroes). * overflow, set if the absolute value of the rounded value is too large to be represented (an infinity or maximal finite value is returned, depending on which rounding is used). * divide-by-zero, set if the result is infinite given finite operands (returning an infinity, either +∞ or −∞). * invalid, set if a real-valued result cannot be returned (like for sqrt(−1), or 0/0), returning a quiet NaN. 

是否在发生任何类型的上述exception时,程序将exception退出? 或者程序会在没有提及任何内容的情况下执行此错误,因此难以调试错误?

像gcc这样的编译器是否能够为一些明显的情况发出警告?

在对程序进行编码时,我可以做些什么来通知错误发生的位置以及发生错误时的类型,以便我可以在代码中轻松找到错误? 请给出C和C ++案例的解决方案。

感谢致敬!

在Linux上,您可以使用GNU扩展名feenableexcept (隐藏在该页面底部)打开浮点exception的陷阱 – 如果您这样做,那么当发生exception时您将收到SIGFPE信号,然后您可以将其捕获你的调试器。 请注意,有时信号会在实际导致问题的信号之后抛出浮点指令,在调试器中给出误导线信息!

有很多选择,但是754引入的一般和默认的理念是陷阱,而是产生特殊的结果,例如可能会或可能不会显示在重要结果中的无穷大。

因此,测试各个操作状态的函数不会像测试结果表示的函数那样频繁使用。

例如,见……

 LIST OF FUNCTIONS Each of the functions that use floating-point values are provided in sin- gle, double, and extended precision; the double precision prototypes are listed here. The man pages for the individual functions provide more details on their use, special cases, and prototypes for their single and extended precision versions. int fpclassify(double) int isfinite(double) int isinf(double) int isnan(double) int isnormal(double) int signbit(double) 

更新:对于那些真正认为FPU ops在默认情况下生成SIGFPE的人,我鼓励你尝试这个程序。 您可以轻松生成下溢,溢出和被零除。 你不会生成什么(除非你在最后一个幸存的VAX或非754 RISC上运行它)是SIGFPE:

 #include  #include  int main(int ac, char **av) { return printf("%f\n", atof(av[1]) / atof(av[2])); } 

在使用Visual C ++的Windows上,您可以使用_control87()等控制哪些浮点exception未被屏蔽。 未屏蔽的浮点exception会生成结构化exception,可以使用__try / __except (以及其他一些机制)来处理。 这完全取决于平台。

如果将浮点exception屏蔽,则另一种与平台相关的方法来检测这些条件是使用_clear87()等清除浮点状态,执行计算,然后使用_status87()等查询浮点状态。

这有什么比DigitalRoss检查结果更好的建议吗? 在大多数情况下,事实并非如此。 如果你需要检测(或控制)舍入(这是不太可能的),那么可能呢?

在使用Borland / CodeGear / Embarcadero C ++的Windows上,默认情况下会取消屏蔽某些浮点exception,这在使用未通过未屏蔽的浮点exception进行测试的第三方库时经常会出现问题。

不同的编译器以不同的方式处理这些错误。

不精确性几乎总是数字除以绝对值大于1的结果(也许是通过trancendental函数)。 使用绝对值> 1.0添加,减去和乘以数字只会导致溢出。

下溢不会经常发生,并且除了迭代函数(如泰勒级数)之外,在正常计算中可能不会引起问题。

溢出是一个通常可以通过某种“无限”比较来检测的问题,不同的编译器会有所不同。

除零是非常值得注意的,因为如果你没有error handling程序,你的程序将(应该)崩溃。 检查红利和除数将有助于避免这个问题。

通常会捕获无效的答案而没有打印某种DOMAIN错误的特殊error handling程序。

[编辑]

这可能会有所帮助:( Sun的数值计算指南) http://docs.sun.com/source/806-3568/

C99引入了处理浮点exception的函数。 在浮点运算之前,您可以使用feclearexcept()清除任何未完成的exception。 在操作之后,您可以使用fetestexcept()来测试设置了哪些exception标志。

在Linux中,您可以通过捕获SIGFPE信号来捕获这些exception。 如果您不采取任何措施,这些例外将终止您的计划。 要设置处理程序,请使用信号函数,传递您希望捕获的信号,以及在信号触发时调用的函数。