主页C++ Builder 资料C++ Builder 参考手册cfloat 浮点数浮点数异常处理
C++ Builder 串口控件
C++ Builder 编程技巧
C++ Builder 操作指南
C++ Builder 参考手册
基础知识
cfloat 浮点数
 • 浮点数类型
 • 浮点数异常处理
 • _finite, _finitel
 • _isinf, _isinfl
 • _isnan, _isnanl
 • _fpclass, _fpclassl
 • _chgsign, _chgsignl
 • _copysign, _copysignl
 • _logb, _logbl
 • _scalb, _scalbl
 • _nextafter, _nextafterl
 • _clear87, _clearfp
 • _control87, _controlfp
 • _status87, _statusfp
 • _fpreset
cmath 数学函数
cstdlib 标准库函数
System 字符串
System 日期和时间
System.Math.hpp 数学函数
其他数据类型
VCL 基础类
VCL 应用程序
Pictures 图片
Graphics 绘图
Additional 控件
System 控件
A ~ Z 字母顺序排列的目录
网友留言/技术支持
浮点数异常处理

如果浮点数运算产生了溢出,或者被零除,会抛出异常,这会影响程序的正常运行,通常处理的方法有两种:

 • 第一种方法:允许计算结果为 +INF、-INF 和 NAN 这些浮点数值,永远不抛出异常。
 • 第二种方法:用 try ... catch 捕获异常,计算结果不会出现 +INF、-INF 和 NAN

相关链接:DOMAIN error 定义域错误

 

允许计算结果为 +INF、-INF 和 NAN 这些浮点数值,永远不抛出异常

禁用浮点数异常的语句只需要在程序启动的时候执行一次,以后所有的浮点数溢出和被零除等都不抛出异常,计算结果为 +INF、-INF 和 NAN

禁用浮点数异常的语句 SetExceptionMask(exAllArithmeticExceptions); std::_control87(MCW_EM, MCW_EM);
头文件 #include <System.Math.hpp> #include <cfloat>
64 位 Windows C++ Builder XE3 及之后的版本 不支持 (缺少库文件)
32 位 Windows C++ Builder XE2 及之后的版本 所有版本的 C++ Builder
备注 新版本 C++ Builder 需要使用这个方法 老版本 C++ Builder 采用的方法,不支持 64 位

测试程序:

#include <System.Math.hpp>
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
  SetExceptionMask(exAllArithmeticExceptions);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
  double a =  1.0;
  double b = -1.0;
  double c =  0.0;

  double x = a / c;
  double y = b / c;
  double z = c / c;

  Memo1->Lines->Add(L"x = " + FloatToStr(x));
  Memo1->Lines->Add(L"y = " + FloatToStr(y));
  Memo1->Lines->Add(L"z = " + FloatToStr(z));
}

运行结果:

 

用 try ... catch 捕获异常,计算结果不会出现 +INF、-INF 和 NAN

对于 C++ Builder 来说,和普通的异常一样,用 try ... catch 或 try ... __finally 处理异常。

测试程序:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  try
   {
     double a =  1.0;
     double b = -1.0;
     double c =  0.0;

     double x = a / c;
     double y = b / c;
     double z = c / c;

     Memo1->Lines->Add(L"x = " + FloatToStr(x));
     Memo1->Lines->Add(L"y = " + FloatToStr(y));
     Memo1->Lines->Add(L"z = " + FloatToStr(z));
   }
  catch(Exception &e)
   {
     MessageBox(Handle, (L"错误:" + e.ClassName() + L"\r\n" + e.Message).c_str(), L"错误信息", MB_OK|MB_ICONEXCLAMATION);
   }
}

通过这个测试程序可以看到:
当任何一句代码产生异常,都会从 try { } 里面跳出,转到 catch(){ } 里面,
在 catch 里面,可以通过 Exception &e 得到异常的类型和错误信息。
如果不希望出错之后放弃所有的计算,需要每条语句都写在一个单独的 try ... catch 里面。

 

相关链接:

_control87SetExceptionMask_matherr_finite_isinf_isnan_fpclass

◤上一页:浮点数类型下一页:_finite, _finitel

C++ 爱好者 -- Victor Chen 的个人网站 www.cppfans.com 辽ICP备11016859号