float浮点数的溢出处理

news/2024/7/3 13:12:00 标签: float, exception, math.h, domain, struct, 编译器

浮点数计算溢出处理问题、浮点数1.#INF和1.#IND 问题

浮点数计算溢出处理问题、浮点数1.#INF和1.#IND 问题浮点数计算溢出处理问题、浮点数1.#INF和1.#IND <wbr>问题

 

昨天遇到了一个关于浮点数计算溢出处理的问题,本来想用 if 语句把条件写好。

可是遇到了很多困难,上网搜了一下,发现一个解决办法:

if 语句把条件写好可以,但是如果遇到幂函数pow(x,y)时,问题就不那么简单了。仔细分析将发现:

 

             y
   x  
负小数负整数0整数小数
负小数无意义有意义有意义有意义无意义
负整数无意义有意义有意义有意义无意义
0无意义无意义有意义有意义有意义
整数有意义有意义有意义有意义有意义
小数有意义有意义有意义有意义有意义


例如:pow(-1.2,-1.2)=-1.#IND。如果要编程处理,至少需要六个if语句。即使如此,也有麻烦:如何判断一个double型的变元的值是整数还是小数?

 


为了处理数学函数运算中出现的异常,VC++提供了一个函数_mather,其原型在<math.h>中:

--------------------------------------------------------------------------------------------------------------

所在头文件:<math.h>

 

函数原型:int _matherr( struct _exception *except );

函数功能:VC++自动调用此函数来判断处理数学函数中出现的异常(不能手动调用)

函数返回值:0返回值用来标志一个错误,非0值标志成功。如果返回0,则错误信息可被显示,错误序号被正确设置。如果返回非0值,没有显示错误信息,错误序号也保持不变。

函数参数:_exception结构包含有如下数据成员:

struct _exception

{
int type 异常类型;
char *name 出错函数名;
double arg1, arg2 函数的第一和第二(如果有的话)参数;
double retval 函数的返回值。

}

-------------------------------------------------------------------------------------------------------------

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

 

 

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

 #include <math.h> #include <string.h> #include <stdio.h> void main() { 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 ) ); } int _matherr( struct _exception *except ) { 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; } }

输出结果


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

 

main函数并没有调用_matherr函数,为什么会出现这种情况呢?这就是VC++编译器为我们做的事情了。它很有可能在数学函数中设置了跳转来实现异常处理,当数学库中的符点函数探测到一个错误时,就调用此函数。


以上是网上的解决办法,我自己也想了一下,这样做的确是比用一般if语句判断好多了,可是这个是系统自动调用的,在什么地方调用不知道,什么时候调用也不知道,不透明,任何的错误都在函数中处理,有时候也不方便。

后来经过不断试验,我发现,float 和double类型的数据,或是各种数学函数,在发生溢出或错误的时候会返回一个异常浮点数,只要我们判断出这个异常,就可以进一步处理,这样的处理了方式相对就自由多了。

 

 

上网找了一些资料:

常见异常的浮点数有:

 

1.#INF:这个值表示“无穷大inf (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当一个整数除以0时便会得到一个1.#INF / inf值;相应的,如果一个负整数除以0会得到 -1.#INF / -inf 值。

1.#IND:这个的情况更复杂,一般来说,它们来自于任何未定义结果(非法)的浮点数运算。"IND"是 indeterminate 的缩写,而"nan"是 not a number 的缩写。产生这个值的常见例子有:对负数开平方,对负数取对数,0.0/0.00.0*∞, ∞/∞ 等。

简而言之,如果遇到 1.#INF / inf,就检查是否发生了运算结果溢出除零,而遇到 1.#IND / nan,就检查是否发生了非法的运算。

 

 

在vc中,可以用float.h中的,用一下函数来判断:

int _isnan(double x) 判断x是不是无效数据(NAN),是返回1,不是返回0

int _finite(double x)判断x是不是无穷大(1.#INF),是返回0,不是返回非零值

 

int _fpclass(double x)用于检验一个浮点数的类型。

_fpclass的返回值有:

 _FPCLASS_SNAN    

 _FPCLASS_QNAN    

 _FPCLASS_NINF    

 _FPCLASS_NN      

 _FPCLASS_ND      

 _FPCLASS_NZ      

 _FPCLASS_PZ      

 _FPCLASS_PD      

 _FPCLASS_PN      

 _FPCLASS_PINF    



到这里,只要调用函数,VC下浮点数溢出的问题,迎刃而解~~~~~

 

 

 

 

 

http://www.vckbase.com/document/viewdoc/?id=437

http://live.aulddays.com/tech/10/double-float-ind-nan-inf/

http://apple.wish365.net/program-not-a-number/

http://www.cppprog.com/2010/0105/190.html


http://www.niftyadmin.cn/n/520897.html

相关文章

WS2801驱动程序C语言,树莓派连接控制WS2801灯带

前言WS2801是一个可编程的灯带&#xff0c;用树莓派来控制WS2801可以实现多种场景&#xff0c;比如实现接入HomeBridge用苹果(Iphone)手机的HomeKit来实现语音控制该灯带&#xff0c;本文仅介绍如何用树莓派来控制WS2801。材料准备树莓派电源(给WS2801供电)WS2801电路图WS2801 …

【专题2:电子工程师 之 上位机】 之 【10.QPushButton按钮】

嵌入式工程师成长之路 系列文章 总目录希望本是无所谓有&#xff0c;无所谓无的&#xff0c;这正如脚下的路&#xff0c;其实地上本没有路&#xff0c;走的人多了&#xff0c;也便成了路原创不易&#xff0c;文章会持续更新文章会同步到作者个人公众号上&#xff0c;感谢扫码关…

随笔记录:时序、看门狗~

2011.3.4堆全局变量 数据高到低增长编译器存放 栈函数调用 压栈设置方向与堆相反 或同向但分区不同基地址分配 再&#xff08;有中断发生&#xff09;去延伸若中断不停发生&#xff0c;且内存延续&#xff0c;栈指针和堆指针地址相同时数据发生冲突&#xff0c; 软件死机若内…

自动存储c语言,C语言中存储类别又分为四类:自动(auto)、静态(static)、寄存器的(register)和外部的(extern)。...

除法运算中注意&#xff1a;如果相除的两个数都是整数的话&#xff0c;则结果也为整数&#xff0c;小数部分省略&#xff0c;如8/3 2&#xff1b;而两数中有一个为小数&#xff0c;结果则为小数&#xff0c;如&#xff1a;9.0/2 4.500000。取余运算中注意&#xff1a;该运算只…

【专题2:电子工程师 之 上位机】 之 【11.QLineEdit输入框】

嵌入式工程师成长之路 系列文章 总目录希望本是无所谓有&#xff0c;无所谓无的&#xff0c;这正如脚下的路&#xff0c;其实地上本没有路&#xff0c;走的人多了&#xff0c;也便成了路原创不易&#xff0c;文章会持续更新文章会同步到作者个人公众号上&#xff0c;感谢扫码关…

堆和栈的区别 (转贴)

http://www.cppblog.com/oosky/archive/2006/01/21/2958.html 堆和栈的区别 (转贴) 非本人作也!因非常经典,所以收归旗下,与众人阅之!原作者不祥! 堆和栈的区别一、预备知识—程序的内存分配一个由c/C编译的程序占用的内存分为以下几个部分1、栈区&#xff08;stack&#xff0…

【专题2:电子工程师 之 上位机】 之 【12.遍历子节点】

嵌入式工程师成长之路 系列文章 总目录希望本是无所谓有&#xff0c;无所谓无的&#xff0c;这正如脚下的路&#xff0c;其实地上本没有路&#xff0c;走的人多了&#xff0c;也便成了路原创不易&#xff0c;文章会持续更新文章会同步到作者个人公众号上&#xff0c;感谢扫码关…

c语言文件写入连续int,c语言fwrite写入int问题,怎么解决?

c语言fwrite写入int问题&#xff0c;怎么解决&#xff1f;#includevoid aaa();struct student{char name[5]; //姓名int age; //年龄int num; //学号char addr[5]; //地址}stu[4];void main(){int i;printf("请输入4个学生姓名、年龄、学号、地址&#xff0c;按回车&#…