`
congfeng02
  • 浏览: 196507 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

捕获数学函数异常

阅读更多

捕获数学函数异常
作者: 江汉石油学院计算机系周云才

下载本文配套源代码

假如我们要用一个数学函数,比如反正弦函数asin(x),如果变元x的值是由用户提供或某个中间结果,则在调用时必须判断其取值范围是合理,是否满|x|<=1?即

if(fabs(x)<=1)
y=asin(x);
else
y=…
对数函数也可作类似的处理。但是如果遇到幂函数pow(x,y)时,问题就不那么简单了。仔细分析将发现:
y
x
负小数 负整数 0 整数 小数
负小数 无意义 有意义 有意义 有意义 无意义
负整数 无意义 有意义 有意义 有意义 无意义
0 无意义 无意义 有意义 有意义 有意义
整数 有意义 有意义 有意义 有意义 有意义
小数 有意义 有意义 有意义 有意义 有意义

例如:pow(-1.2,-1.2)=-1.#IND。如果要编程处理,至少需要六个if语句。即使如此,也有麻烦:如何判断一个double型的变元的值是整数还是小数?
为了处理数学函数运算中出现的异常,VC++提供了一个函数_mather,其原型在<math.h>中:
int _matherr( struct _exception *except );
为了利用此函数,只需在应用数学函数的地方定义一个这样的函数,例如
#include <math.h>
#include <stdio.h>
void main()
{
	double x,y,z;
	x=-1.23;
	y=-1;
	z=pow(x,y);
	printf("%g\n",z);
	y=-1.1;
	z=pow(x,y);
	printf("%g\n",z);
}

int _matherr(struct _exception *except)
{
char* errorString[] = {"_DOMAIN","_SING", "_OVERFLOW", "_PLOSS", 
"_TLOSS", "_UNDERFLOW"};
	printf("Error function name is %s\n",except->name);
	printf("The varianbles arg1=%g,arg2=%g\n",except->arg1,except->arg2);
	printf("The error type = %s\n",errorString[except->type]);
	printf("The error value=%g\n",except->retval);
	except->retval=1234;
	printf("After handling error value=%g\n",except->retval);
	return 1;
}
编译、运行,结果为
-0.813008
Error function name is pow
The varianbles arg1=-1.23,arg2=-1.1
The error type = _SING
The error value=-1.#IND
After handling error value=1234
1234
Press any key to continue

第一行为-1.23的倒数,第二~六两行是_matherr函数的输出,第七行是主函数的输出。
也许有人会说,main函数并没有调用_matherr函数,为什么会出现这种情况呢?这就是VC++编译器为我们做的事情了。它很有可能在数学函数中设置了跳转来实现异常处理,当数学库中的符点函数探测到一个错误时,就调用此函数。下面是有关_matherr函数的一些说明:

1、返回值:类型是整型的。按惯例,0返回值用来标志一个错误,非0值标志成功。如果返回0,则错误信息可被显示,错误序号被正确设置。如果返回非0值,没有显示错误信息,错误序号也保持不变。

2、参数:except指针指向一个包含错误信息的结构 struct _exception。
_exception结构包含有如下数据成员:
int type 异常类型;
char *name 出错函数名;
double arg1, arg2 函数的第一和第二(如果有的话)参数;
double retval 函数的返回值。

注意:数学函数的错误类型定义如下:
_DOMAIN 变元定义域错误;
_SING 变元奇异点错误;
_OVERFLOW 溢出错误;
_PLOSS 精度部分遗失;
_TLOSS 精度丢失;
_UNDERFLOW 下溢错误,结果太小,无发表示。

下面是MSDN给我们提供的一个示例供大家参考:

/* MATHERR.C illustrates writing an error routine for math 
 * functions. The error function must be:
 *      _matherr
 */

#include <math.h>
#include <string.h>
#include <stdio.h>

void main()
{
    /* Do several math operations that cause errors. The _matherr
     * routine handles _DOMAIN errors, but lets the system handle
     * other errors normally.
     */
    printf( "log( -2.0 ) = %e\n", log( -2.0 ) );
    printf( "log10( -5.0 ) = %e\n", log10( -5.0 ) );
    printf( "log( 0.0 ) = %e\n", log( 0.0 ) );
}

/* Handle several math errors caused by passing a negative argument
 * to log or log10 (_DOMAIN errors). When this happens, _matherr
 * returns the natural or base-10 logarithm of the absolute value
 * of the argument and suppresses the usual error message.
 */
int _matherr( struct _exception *except )
{
    /* Handle _DOMAIN errors for log or log10. */
    if( except->type == _DOMAIN )
    {
        if( strcmp( except->name, "log" ) == 0 )
        {
            except->retval = log( -(except->arg1) );
            printf( "Special: using absolute value: %s: _DOMAIN "
                     "error\n", except->name );
            return 1;
        }
        else if( strcmp( except->name, "log10" ) == 0 )
        {
            except->retval = log10( -(except->arg1) );
            printf( "Special: using absolute value: %s: _DOMAIN "
                     "error\n", except->name );
            return 1;
        }
    }
    else
    {
        printf( "Normal: " );
        return 0;    /* Else use the default actions */
    }
}
输出结果

Special: using absolute value: log: _DOMAIN error
log( -2.0 ) = 6.931472e-001
Special: using absolute value: log10: _DOMAIN error
log10( -5.0 ) = 6.989700e-001
Normal: log( 0.0 ) = -1.#INF00e+000

作者信息:
姓名:周云才
邮箱:zyc262@163.net
联系地址:江汉石油学院计算机系 邮编 434023
分享到:
评论

相关推荐

    Python编程基础&AI数学 视频 AI和Datacom-Network Automation Developer

    目录:网盘文件永久连接 AI 数学基础01 课程介绍 AI 数学基础02 AI数学概览 AI 数学基础03 矩阵的概念及矩阵计算 AI 数学基础04 线性变换...Python编程基础11 IO操作与异常捕获 Python编程基础12 常用工具库 Pytho

    C++和面向对象数值计算

    3.11 标准数学函数库 3.12 多项式求值 3.13 梯形公式和simpson公式 3.14 练习 第4章 命名空间和文件 4.1 命名空间 4.1.1 使用声明和指令 4.1.2 多重接口 4.1.3 命名空间别名 4.1.4 无名命名...

    写给大忙人看的JAVA SE 8

    8.3 新的数学函数 169 8.4 集合 170 8.4.1 集合类中添加的方法 170 8.4.2 比较器 171 8.4.3 Collections类 173 8.5 使用文件 173 8.5.1 读取文件行的流 173 8.5.2 遍历目录项的流 175 8.5.3 Base64编码 176 8.6 注解...

    C++大学教程,一本适合初学者的入门教材(part2)

    3.3 数学函数库 3.4 函数 3.5 函数定义 3.6 函数原型 3.7 头文件 3.8 随机数产生器 3.9 案例:机会游戏与enum简介 3.10 存储类 3.11 作用域规则 3.12 递归 3.13 使用递归举例:Fibonacci数列 3.14 递归...

    C++大学教程,一本适合初学者的入门教材(part1)

    3.3 数学函数库 3.4 函数 3.5 函数定义 3.6 函数原型 3.7 头文件 3.8 随机数产生器 3.9 案例:机会游戏与enum简介 3.10 存储类 3.11 作用域规则 3.12 递归 3.13 使用递归举例:Fibonacci数列 3.14 递归...

    TCL培训教程(全)

    4.3数学函数 5List 5.1list命令 5.2concat命令: 5.3lindex命令 5.4llength命令 5.5linsert命令 5.6lreplace命令: 5.7lrange 命令: 5.8lappend命令: 5.9lsearch 命令: 5.10lsort命令: 5.11split命令: 5.12join命令 6...

    java实现别踩白块儿源码-JavaCode:我专门介绍以下主题:Java基本数据类型,声明语句,表达式语句,导入类库,用户输入之外,检查有效

    我专门介绍以下主题:Java基本数据类型,声明语句,表达式语句,导入类库,用户输入之外,检查有效输入,捕获输入中的错误,数学函数,if语句,关系运算符,逻辑运算符,三元运算符,switch语句和循环。 类变量与...

    python cookbook(第3版)

    14.9 捕获异常后抛出另外的异常 14.10 重新抛出最后的异常 14.11 输出警告信息 14.12 调试基本的程序崩溃错误 14.13 给你的程序做基准测试 14.14 让你的程序跑的更快 第十五章:C语言扩展 15.1 使用ctypes...

    LuaFramework_UGUI_V2-master.zip

    当lua出现异常,能够同时捕获c#端和lua端堆栈,便于调试 print信息,在编辑器点击日志, 能自动打开对应lua文件 支持unity所有版本 支持Lua hook C#相代码实现,一定程度上支持利用Lua代码修改C#端代码的bug(暖更新...

    Java范例开发大全 (源程序)

     实例47 try…catch…finally捕获异常的实例 67  实例48 try…catch嵌套捕获异常的实例 68  4.4 throws声明异常 69  实例49 throws声明异常实例一 69  实例50 throws声明异常实例二 70  4.5 throw抛出...

    java范例开发大全(pdf&源码)

    实例47 try…catch…finally捕获异常的实例 67 实例48 try…catch嵌套捕获异常的实例 68 4.4 throws声明异常 69 实例49 throws声明异常实例一 69 实例50 throws声明异常实例二 70 4.5 throw抛出异常 72 实例51 throw...

    java范例开发大全源代码

     实例47 try…catch…finally捕获异常的实例 67  实例48 try…catch嵌套捕获异常的实例 68  4.4 throws声明异常 69  实例49 throws声明异常实例一 69  实例50 throws声明异常实例二 70  4.5 throw抛...

    java范例开发大全

    实例47 try…catch…finally捕获异常的实例 67 实例48 try…catch嵌套捕获异常的实例 68 4.4 throws声明异常 69 实例49 throws声明异常实例一 69 实例50 throws声明异常实例二 70 4.5 throw抛出异常 72 实例51 throw...

    delphi 开发经验技巧宝典源码

    0059 如何捕获异常 37 0060 TStrings与TStringList的使用 37 0061 如何实现窗体文件转换 37 第3章 程序算法 39 3.1 计算类算法 40 0062 如何计算1~100的阶乘和 40 0063 如何实现最大公约数 40 0064 ...

    delphi 开发经验技巧宝典源码06

    0059 如何捕获异常 37 0060 TStrings与TStringList的使用 37 0061 如何实现窗体文件转换 37 第3章 程序算法 39 3.1 计算类算法 40 0062 如何计算1~100的阶乘和 40 0063 如何实现最大公约数 40 0064 ...

    深入浅出Rxjs

    包括如何捕获异常和实现重试。 第10章 多播。这⼀章介绍如何让⼀个数据源的内容被多个观察者接 收,包括Subject的使⽤⽅法和RxJS对各种多播场景的⽀持。 第11章 掌握时间的Scheduler。这⼀章介绍RxJS中Scheduler的...

    lua 程序设计学习.doc 版

    8.4 异常和错误处理 8.5 错误信息和回跟踪(Tracebacks) 第9章 协同程序 9.1 协同的基础 9.2 管道和过滤器 9.3 用作迭代器的协同 9.4 非抢占式多线程 第10章 完整示例 10.1 Lua作为数据描述语言使用 10.2 马尔可夫...

Global site tag (gtag.js) - Google Analytics