Friday, February 14, 2014

overflow recgonition 判断溢出

C++ 计算时判断溢出

方法 一
===========================================================
short, int, long 类型
a). 相加的时候,例如 a + b, 判断 INT_MAX - a 和 b的大小
b). 相减的时候,例如 a - b, 可以转换为a + (-b),  然后类似 上一条来判断。

要注意的是,b变为-b的时候,有可能发生溢出,需要单独判断。
如果b不是INT_MIN,可以转换后是直接按a) 来做
如果b是INT_MIN,要把 -b分拆为 -(b+1) 和1,因为是特例,我们可以直接改写为 a + -(b+1) + 1, 因为后面两个直接溢出,可以调整顺序,变为a + 1 + -(b+1)

以上这个办法,有缺点
第一、处理起来啰嗦
第二,INT_MAX-a本身就有可能溢出

方法 二
===========================================================
转换为上下限更高的数据类型,然后来判断
比如 int 类型的 a+b,我们可以转换为 (long)a + (long)b, 然后和INT_MAX 或者 INT_MIN比较
如果是long,可以转化为long long
如果是long long, 可以转化为double
double以后,就有内置函数类比较了 
http://www.cplusplus.com/reference/cmath/isfinite/
http://www.cplusplus.com/reference/cmath/isinf/

方法 二
===========================================================
对于 short, int, long, long long 类型的数据a 和 b 的加减法,判断溢出通用的做法可以是
先判断是否同号,
如果相加异号 或者 相减同号,无溢出
如果相加同号 或者 相减异号,换为无符号数,unsigned的,先运算c = a + b
然后通过比较a, b 和c的符号来判断是否溢出。



而对于float, double, long double 这些,会有内置的函数isfinite,isinf来比较, 参见
http://www.cplusplus.com/reference/cmath/isfinite/
http://www.cplusplus.com/reference/cmath/isinf/

/* isinf example */
#include <stdio.h>      /* printf */
#include <math.h>       /* isinf, sqrt */

int main()
{
  printf ("isinf(0.0)       : %d\n",isinf(0.0));
  printf ("isinf(1.0/0.0)   : %d\n",isinf(1.0/0.0));
  printf ("isinf(-1.0/0.0)  : %d\n",isinf(-1.0/0.0));
  printf ("isinf(sqrt(-1.0)): %d\n",isinf(sqrt(-1.0)));
  return 0;
}

No comments:

Post a Comment