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

  一帖子报告用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的输入参数是负数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值