如果浮点数运算产生了溢出,或者被零除,会抛出异常,这会影响程序的正常运行,通常处理的方法有两种:
• 第一种方法:允许计算结果为 +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 里面。
相关链接:
• _control87 • SetExceptionMask • _matherr • _finite • _isinf • _isnan • _fpclass
|