我在visual studio express中使用c ++生成随机表达式树,用于遗传算法类型的程序。
因为它们是随机的,所以树通常会生成:除以零,溢出,下溢以及返回“inf”和其他字符串。我可以为字符串编写处理程序,但文献让我对其他人感到困惑。如果我理解正确,我必须先设置一些标志?
建议和/或指向某些文献的指针将不胜感激。 编辑:double变量中返回的值为1.#INF或-1。#IND。我把它们称为字符串是错误的。
答案 0 :(得分: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 {};
使用结构化异常处理程序将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);
然后您可以使用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;
}
答案 1 :(得分: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)
}
这里的一些混淆可能是使用“例外”一词。在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 :(得分:1)
C ++运行时环境在这里没有任何帮助。您必须自己在代码中明确执行这些检查。当然,除非你正在调用的函数正在进行这些检查 - 在这种情况下,它取决于它们在出错时的行为方式。
让我解释一下:
double divide(double a, double b) {
return a / b; // undefined if b is zero
}
实际上应该是
double divide(double a, double b) {
if( b == 0 ) {
// throw, return, flag, ... you choose how to signal the error
}
return a / b; // b can't possibly be zero here
}
如果代码在被零除的情况下失败,那么你就不得不深入挖掘,以便在出现错误威胁的情况下找到它的作用。它扔了吗?设置一面旗帜?询问作者和/或阅读来源。
以下是例外情况的示例:
struct bad_value : public std::exception { };
double divide(double a, double b) {
if( b == 0 ) throw bad_value("Division by zero in divide()");
return a / b; // b can't possibly be zero here
}
// elsewhere (possibly in a parallel universe) ...
try {
double r1 = divide(5,4);
double r2 = divide(5,0);
} catch( bad_value e ) {
// ...
}
答案 3 :(得分:-2)
从未尝试过,但假设除以零会引发异常,您可以将代码包装在try / catch中,如下所示:
试 { //潜在除以零... } 抓住(...) { // ...捕获所有异常 }