如何使用try ... catch来捕获浮点错误?

Pet*_*art 11 c++ error-handling

我在visual studio express中使用c ++生成随机表达式树,用于遗传算法类型的程序.

因为它们是随机的,所以树通常会产生:除以零,溢出,下溢以及返回"inf"和其他字符串.我可以为字符串编写处理程序,但文献让我对其他人感到困惑.如果我理解正确,我必须先设置一些标志?

建议和/或指向一些文献的指针将不胜感激.编辑:double变量中返回的值为1.#INF或-1.#IND.我称他们为字符串是错误的.

aka*_*ice 10

根据 http://msdn.microsoft.com/en-us/library/aa289157%28v=vs.71%29.aspx#floapoint_topic8,
似乎可以在MSVC中抛出C++异常

创建例外类:

class float_exception : public std::exception {};
class fe_denormal_operand : public float_exception {};
class fe_divide_by_zero : public float_exception {};
class fe_inexact_result : public float_exception {};
class fe_invalid_operation : public float_exception {};
class fe_overflow : public float_exception {};
class fe_stack_check : public float_exception {};
class fe_underflow : public float_exception {};
Run Code Online (Sandbox Code Playgroud)

使用结构化异常处理程序将C++映射到FPU异常

void se_fe_trans_func( unsigned int u, EXCEPTION_POINTERS* pExp )
{
    switch (u)
    {
    case STATUS_FLOAT_DENORMAL_OPERAND:   throw fe_denormal_operand();
    case STATUS_FLOAT_DIVIDE_BY_ZERO:     throw fe_divide_by_zero();
    etc...
    };
}
. . .
_set_se_translator(se_fe_trans_func);
Run Code Online (Sandbox Code Playgroud)

然后你可以使用try catch

try
{
    floating-point code that might throw divide-by-zero 
   or other floating-point exception
}
catch(fe_divide_by_zero)
{
    cout << "fe_divide_by_zero exception detected" << endl;
}
catch(float_exception)
{
    cout << "float_exception exception detected" << endl;
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该是批准的答案:它对应于原始问题(接受的答案基本上说"你不应该打扰",第二个说"你不能"(这是不正确的). (2认同)

Geo*_*rge 7

你确定要抓住它们而不是忽略它们吗?假设你只是想忽略它们:

请参阅:http: //msdn.microsoft.com/en-us/library/c9676k6h.aspx

对于_MCW_EM掩码,清除掩码会设置异常,从而允许硬件异常; 设置掩码会隐藏异常.

所以你想要做这样的事情:

#include <float.h>
#pragma fenv_access (on)

void main()
{
    unsigned int fp_control_word;
    unsigned int new_fp_control_word;

    _controlfp_s(&fp_control_word, 0, 0);

    // Make the new fp env same as the old one,
    // except for the changes we're going to make
    new_fp_control_word = fp_control_word | _EM_INVALID | _EM_DENORMAL | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT;
    //Update the control word with our changes
    _controlfp_s(&fp_control_word, new_fp_control_word, _MCW_EM)


}
Run Code Online (Sandbox Code Playgroud)

这里的一些混淆可能是使用"例外"一词.在C++中,这通常指的是语言内置的异常处理系统.浮点异常完全是一个不同的野兽.标准FPU需要支持的例外都在IEEE-754中定义.这些发生在浮点单元内部,根据浮点单元的控制标志的设置方式,可以执行不同的操作.通常会发生以下两种情况之一:1)忽略异常,FPU设置一个标志,指示其状态寄存器中发生错误.2)FPU不会忽略该异常,因此生成中断,并且调用为浮点错误设置的任何中断处理程序.通常,这对您有好处,比如让您在调试器中的那行代码中断或生成核心文件.

您可以在此处找到有关IEE-754的更多信息:http://www.openwatcom.org/ftp/devel/docs/ieee-754.pdf

一些额外的浮点引用:http : //docs.sun.com/source/806-3568/ncg_goldberg.html http://floating-point-gui.de/

  • 还要注意,我已经看到图书馆对浮点控制字的设置进行了争论,每个都强加于另一个.几乎与打印机驱动程序更改程序源下的语言环境一样糟糕... (2认同)
  • @Peter Stewart:要记住你的答案,一个重要的事情是,如果你得到一个NaN(非数字),比较运算符就不会像你认为的那样工作.例如,检测结果是否为NaN的一种简单方法是检查"f!= f"是否返回true.您可能也想检查一下.看到这个问题:http://stackoverflow.com/questions/570669/checking-if-a-double-or-float-is-nan-in-c (2认同)