C++ Builder 浮点数异常处理

C++ Builder 参考手册C++ Builder 浮点数异常处理


Floating point division by zero.
Floating point overflow.
Invalid floating point operation.

在程序运行中,可能会遇到弹出浮点数错误的提示框,甚至可能会不停的弹出这样的提示框,即 “浮点数被 0 除”、“浮点数溢出”、“无效的浮点数操作” 等:

Floating point division by zero.
Floating point overflow.
Invalid floating point operation.

C++ Builder 对浮点数异常的处理分两种情况:

  1. 抛出异常,默认是这样处理的,就像本文前面描述那样,如果没有放在 try 里面就会直接弹出错误提示框;
  2. 不抛出异常,有异常的算式的计算结果为 NAN,+INF,-INF。

执行如下代码之后,就不抛出浮点数异常了:

std::_control87(MCW_EM, MCW_EM);

SetExceptionMask(exAllArithmeticExceptions);

_control87 需要包含的头文件是 #include <cfloat>
SetExceptionMask 需要包含的头文件是 #include <System.Math.hpp>

NAN: 是 not a number (不是数) 的缩写,是无法计算的算式的计算结果;
+INF: 是 +infinity (+∞,正无穷大) 的缩写;
-INF: 是 -infinity (-∞,负无穷大) 的缩写。

例如:
1.0 / 0.0 等于 +INF;
-1.0 / 0.0 等于 -INF;
0.0 / 0.0 等于 NAN。

用 std::_isnan(x) 判断浮点数 x 是否为 NAN,用 std::_finite(x) 判断 x 是否为实数,即 -∞ < x < +∞ 为真,其余为假,这两个函数在 #include <cfloat> 里面。

如果 +INF、-INF 和 NAN 都不是计算结果期望的值,可以用 std::_finite 函数判断计算结果。

以下代码演示了屏蔽浮点数异常的有异常的算式的计算结果:

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
    SetExceptionMask(exAllArithmeticExceptions);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    double a, b;
    UnicodeString s;

    a = -1.0;
    b = 0.0;
    s.cat_sprintf(L"%g / %g = %g\r\n", a, b, a/b);

    a = 1e300;
    b = 1e-50;
    s.cat_sprintf(L"%g / %g = %g\r\n", a, b, a/b);

    a = 0.0;
    b = 0.0;
    s.cat_sprintf(L"%g / %g = %g\r\n", a, b, a/b);

    Memo1->Lines->Text = s;
}
//---------------------------------------------------------------------------

执行结果为:

屏蔽浮点数异常的有异常的算式的计算结果

-1 / 0 = -INF 是因为任何负数除以 0 都等于负无穷大;
1e+300 / 1e-50 = +INF 是因为计算结果大于浮点数能够表示的最大值;
0 / 0 = -NAN 是因为无法计算 0 除以 0 的值。


相关:


C++ Builder 参考手册C++ Builder 浮点数异常处理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容