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

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

文章来自:http://www.cnblogs.com/aqxin/archive/2011/05/20/2052045.html

昨天遇到了一个关于浮点数计算溢出处理的问题,本来想用 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给我们提供的一个示例供大家参考:

/* 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

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     /* signaling NaN */

_FPCLASS_QNAN     /* quiet NaN */

_FPCLASS_NINF     /* negative infinity */

_FPCLASS_NN       /* negative normal */

_FPCLASS_ND       /* negative denormal */

_FPCLASS_NZ       /* -0 */

_FPCLASS_PZ       /* +0 */

_FPCLASS_PD       /* positive denormal */

_FPCLASS_PN       /* positive normal */

_FPCLASS_PINF     /* positive infinity */



到这里,只要调用函数,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

浮点数溢出 核心: 浮点数溢出与整数的溢出是不一样的\color{red}{浮点数溢出与整数的溢出是不一样的}浮点数溢出与整数的溢出是不一样的 上溢出: 数值增大,直到阶码全为1,然后尾数全为0,表示无穷,如果要 print 输出的话,会输出 INF —— infinity 无穷 #include <iostream> using namespace std; void main() { ... 阅读详情

相关推荐

C语言的数值溢出问题(中)

浮点数的数值溢出问题: [注]整型数据的表示范围是连续的, 而浮点型数据的表示范围并不是连续的(严格来说): 这是因为浮点型数据在内存中以阶码(决定了数据的表示范围)+尾数(决定了表示精度)的形式存储. [注]当下溢出现象发生时, 系统会将结果处理成机器0(因为这个数已经小到足够接近0, 且无法用浮点数进行表示). 数值溢出的危害: 解决对策: 从小范围数据到大范围数据: 从高精度数据向低精度数据转换时, 会损失什么信息? 数值精度损失举例: 问题浮点数在内存中..

weixin_42048463的博客 3223

STARCCM+学习记录

starccm+使用问题

bohemian_zzx的博客 5606

浮点数运算以及溢出问题

1. 浮点数运算(加减)的步骤:对阶、尾数加减、尾数规格化、尾数舍入、溢出判断 2. 关于浮点数溢出的详细说明

qq_43527718的博客 1万+

c语言中1. ind00,浮點數計算溢出處理問題、浮點數1.#INF1.#IND 問題

昨天遇到了一個關於浮點數計算溢出處理的問題,本來想用if語句把條件寫好。可是遇到了很多困難,上網搜了一下,發現一個解決辦法:if語句把條件寫好可以,但是如果遇到冪函數pow(x,y)時,問題就不那么簡單了。仔細分析將發現:yx負小數負整數0整數小數負小數無意義有意義有意義有意義無意義負整數無意義有意義有意義有意義無意義0無意義無意義有意義有意義有意義整數有意義有意義有意義有意義有意義小數有意義有意...

weixin_34828613的博客 545

float浮点数溢出处理

浮点数计算溢出处理问题浮点数1.#INF1.#IND 问题浮点数计算溢出处理问题浮点数1.#INF1.#IND 问题<br /> <br />昨天遇到了一个关于浮点数计算溢出处理问题,本来想用 if 语句把条件写好。<br />可是遇到了很多困难,上网搜了一下,发现一个解决办法:<br />if 语句把条件写好可以,但是如果遇到幂函数pow(x,y)时,问题就不那么简单了。仔细分析将发现:<br />              y<br />   x  负小数负整数0整数小数负小数无意义有意义有意

happyflovef的专栏 2万+

浮点数计算常见错误1.#INF, 1.#IND#QNAN

编程时,可能会从您的代码中产生某些错误条件。如果编译器捕获任何编译错误,它将停止编译并告诉您错误所在位置。编译器还可能会对某些构造发出警告,这些构造可能会或可能不会在运行期间给您带来问题。 以下是您作为程序员在执行浮点算术(任何加法、减法、乘法除法)时应注意的一些浮点条件,即(QNAN SNAN)条件错误。 正数 负数 意义 1.#INF -1.#INF Infinity无穷大 1.#SNAN -1.#SNAN Signalling NaN .

novanova2009的博客 1万+

1.#INF / inf

1.#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用 0 除一个整数时便会得到一个1.#INF / inf值;相应的,如果用 0 除一个负整数也会得到 -1.#INF / -inf 值。 2.-1.#IND / nan:这个的情况更复杂,一般来说,它们来自于任何未定义结果(非法...

潮湿的桥 5883

打印浮点数输出 1.#IND 1.#INF nan inf 等解决

进行浮点数编程时,如果没有注意,常常会出现输出类似1.#IND,1.#INF或者nan,inf之类奇怪的输出。这通常隐含了浮点数操作的异常。 特殊浮点数的含义 1.#INF/inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了double类型的最大值)。例如,当用 0 除一个整数时便会得到一个1.#INF/inf值;相应的,如果用 0 除一个负整数也会得到-1.#INF/-inf值。 -1.#IND/nan:...

qq_32584715的博客 2781

浮点数编程常见异常( -1.#IND00, 1.#INF00 nan, inf)

好像以前遇到过这种情况。 百度了一下。 进行浮点数编程时,如果没有注意,常常会出现输出类似 1.#IND, 1.#INF 或者 nan, inf 之类奇怪的输出。这通常隐含了浮点数操作的异常。 特殊浮点数的含义 1.#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用

天亮说晚安 2万+

1.#IND 1.#INF nan inf 1.#QNAN SNaN 问题的解决

内容整理自网络 进行浮点数编程时,如果没有注意,常常会出现输出类似 1.#IND, 1.#INF 或者 nan, inf 之类奇怪的输出。这通常隐含了浮点数操作的异常。 特殊浮点数的含义 1.#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用 0 除一个整数时便会得

求知若饥,知行合一 7160

c++ 出现1.#IND1.#INF

说明程序中做除法时发生了除0。那程序编译怎么能通过呢? 原来除数为0有两种情况。   (1)除数显式为0,无论是整型还是浮点型都不能通过编译。    如:cout  会显示: 错误 1 error C2124: 被零除或对零求模    (2)除数隐式为0,无论是整型还是浮点型都能通过编译,但整型将报错且其后程序不再执行。浮点型执行得到正无穷大或负无穷大,依被除数而定,且其后程序正常执

KUAILE123的专栏 7516

C语言除0引发的思考

进行浮点数编程时,如果没有注意,常常会出现输出类似 1.#IND, 1.#INF 或者 nan, inf 之类奇怪的输出。这通常隐含了浮点数操作的异常。 进行整数除0的时候,程序会检查出一个错误,比如对于这个代码: #include #include int main() { int m; m=1/0; printf("%d",m); return 0; }

u011688130的专栏 3237

float除0

进行浮点数编程时,如果没有注意,常常会出现输出类似 1.#IND,1.#INF 或者 nan, inf 之类奇怪的输出。这通常隐含了浮点数操作的异常。 特殊浮点数的含义 1.#INF / inf:这个值表示“无穷大 (infinity 的缩写)”,即超出了计算机可以表示的浮点数的最大范围(或者说超过了 double 类型的最大值)。例如,当用 0 除一个整数时便会得到一个1.#INF / 

龙崎的专栏 4664

浮点数:一种有漏洞的抽象【译】

译自:Floating point numbers are a leaky abstraction Posted on 6 April 2009 by John   “有漏洞的抽象”(leaky abstraction)一词源自Joel Spolsky,他用这个术语表示编程时既能让人免受凌乱...

chuange6363的博客 147

NANINF产生与处理

C语言当中的nan表示not a number,等同于 #IND:indeterminate (windows)产生:对浮点数进行了未定义的操作;对负数开方,对负数求对数,0.0/0.0,0.0*inf、inf/inf、inf-inf这些操作都会得到nan。(0/0会产生操作异常;0.0/0.0不会产生操作异常,而是会得到nan);在GNU中,使用宏:float NAN对浮点数赋值;判定:库函数方...

u012226625的专栏 1万+

1.2浮点类型

1.浮点类型 float: 字长:32, 范围:±(1.20*10^-38 ~ 3.40*10^38), 0, ±inf, nan, 有效数字:7 输入(scanf):%f 输出(printf):%f,%e double: 字长:64, 范围:±(2.2*10^-308 ~ 1.79*10^308),0, ±inf, nan, 有效数字:7 输入(scanf):%lf 输出(printf):%f

jieqiong1的博客 889
上一篇: C++字符串转化为数字的库函数
下一篇: 详解VC6.0中自己手动实现代码注释和取消注释的工具栏按钮功能
梦起
博客等级 码龄15年 0粉丝 1原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值