您的位置:首页 > 其它

数学函数的异常捕获——Ada应用实例之十

2010-05-18 18:00 543 查看
  一帖子报告用C++语言编写了龙格——库塔方法解一个状态方程的程序,编译系统是Borland C++。程序运行过程中出现异常,错误信息是“floating point error”。
  笔者也用Borland C++试了一下,确实出错,但DEBUG状态下停在一条fprintf语句处,这里显然不是发生异常的地方。估计是浮点运算出错。但程序中有大量的算术运算和数学函数调用,很难通过单步运行来定位错误。
  首先怀疑数学函数调用。这可通过调用C++数学库中的函数_matherr来发现数学函数调用的异常。该函数的原型在<math.h>中:
  int _matherr( struct _exception *except );
  为了利用此函数,只需在程序中定义一个这样的函数,例如:
int _matherr(struct _exception *except)
{
const char* errorString[] =
{
"", /*异常类型从1开始编号,因此[0]留空*/
"_DOMAIN(参数域错误)",
"_SING(参数奇异)",
"_OVERFLOW(上溢)",
"_UNDERFLOW(下溢)",
"_TLOSS(丢失全部精度)",
"_PLOSS(丢失部分精度)"
};
printf("出现异常的数学函数名称:%s/n",except->name);
printf("该函数的输入参数:参数1=%g, 参数2(如果有)=%g/n",except->arg1,except->arg2);
printf("异常类型:%s/n",errorString[except->type]);
printf("该函数的返回值:%g/n",except->retval);
return 1;
}

  然后在这个函数中设了一个断点。运行时果然进入了这个函数,原来是 sqrt的参数是负数,所以出现异常。
  如果用Ada编程,那么事情就简单多了。设有以下程序:
with Ada.Exceptions; use Ada.Exceptions;
with Ada.Numerics.Elementary_Functions;
use Ada.Numerics.Elementary_Functions;
with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
r : Float;
begin
r := Sqrt (-1.0);
exception
when Event : others =>
Put ("Unexpected exception:");
Put_Line (Exception_Name (Event));
Put_Line (Exception_Message (Event));
end Main;

  上述程序运行后将输出如下信息:
Unexpected exception:ADA.NUMERICS.ARGUMENT_ERROR
Exception name: ADA.NUMERICS.ARGUMENT_ERROR
Message: a-ngelfu.adb:933 instantiated at a-nuelfu.ads:18

  最后一行指出异常发生的源文件位置。文件a-ngelfu.adb是数学库的源文件,在933行附近的代码是:
function Sqrt (X : Float_Type'Base) return Float_Type'Base is
begin
if X < 0.0 then
raise Argument_Error; -- 933行

-- Special case Sqrt (0.0) to preserve possible minus sign per IEEE

elsif X = 0.0 then
return X;

end if;

return Float_Type'Base (Aux.Sqrt (Double (X)));
end Sqrt;

  由此可见,异常原因是sqrt的输入参数是负数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: