题目描述:
求和函数 addOK /**addOK- 判断 x+y 是否产生溢出*例子:addOK (0x80000000,0x80000000)=0,addOK (0x80000000,0x70000000)=1,*合法运算符号:!~&^|+<<>>*/int addOK(int x,int y){/**************/return/******/;}
判断整数相加是否溢出分为两类:一种是无符号整数相加,一种是带符号整数相加,而这个题要求的是带符号整数相加。如果只想看这道题答案及结论,直接移步到最后位运算代码。
我们首先来看一下无符号整数的溢出如何判断:
下面给出的是无符号数相加的公式:(上面为没有溢出的情况,下面为溢出的情况)
对一个字长为n的无符号数加法运算,当x+y>=2^n时,第n+1位被程序舍去,相当于在x+y的和的基础上减去了2^n。由于x,y<=(2^n)-1,所以有x+y<x(或者x+y<y)。即发生溢出时一定满足result<x and result<y。
我们可以举个反例,假设result>=x 即x+y-2^n>=x 移项后得y>=2^n,由于x,y<=(2^n)-1,所以这是不可能的。
无符号数判断溢出的代码如下:
int uadd_ok(unsigned x,unsigned y){
unsigned sum=x+y;
return sum>=x;
}
有符号整型数加法的溢出分为正溢出与负溢出,正溢出是指两个非负数相加却得负数的情况,而负溢出是指两个负数相加却得正数的情况。
下面给出的是带符号数相加的公式:
无符号数判断溢出的代码如下:
int tadd_ok(int x,int y){
int sum=x+y;
int neg_over=x<0&&y<0&&sum>=0;//负溢出:如果两个负数相加结果是正数
int pos_over=x>=0&&y>=0&&sum<0;//正溢出:如果两个正数相加结果是负数
return !neg_over&&!pos_over;
}
最终位运算代码如下:
分析:
最终目的使溢出return 0,不会溢出return 1。
正数与负数之和不会溢出。
符号相同,则判断两数之和的符号与加数中的任一数的符号是否相同即可,若不相同则为发生溢出。
int a = x>>31; //x的符号位
int b = y>>31; //y的符号位
int sum = (x+y)>>31; //x+y的符号位
1.判断两个数符号是否相同(a^b)
相同为0,不同为1,两数符号不同不会溢出直接return 1。
2.在两个数符号相同的前提下判断和的符号与两个数是否相同(c^a)
相同不溢出 (c^a)=0 为了使不会溢出return 1 所以加在(c^a)前加!