private int add(int x, int y)
{
return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}
以上代码实现两个数相加,注释说明是为防相加后溢出。
请高手解释这行代码防溢出的原理。
{
return ((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
}
以上代码实现两个数相加,注释说明是为防相加后溢出。
请高手解释这行代码防溢出的原理。
((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) 是去掉最高位的加法, 最高位是两个一定是0,相加不会溢出。
& 0x80000000 是 与 1000...000 位乘运算,取最高位。计算最高位加法时,溢出时进位去掉, 0+0=1+1=0 0+1=1+0=1 正好是异或运算。
所以上面三个数做xor:((x&0x7FFFFFFF) + (y&0x7FFFFFFF)) ^ (x&0x80000000) ^ (y&0x80000000);
二进制 1+1=(1)0 考虑溢出,高位的1被溢出,只留下低位的0
二进制 1+0=1 没有发生溢出
二进制 0+0=0 没有发生溢出再看二进制的异或
二进制 1^1=0 没有发生溢出
二进制 1^0=1
二进制 0^0=0所以
二进制 1+1=(1)0=1^1 考虑溢出
二进制 1+0=1=1^1
二进制 0+0=0=0^0
即加法和异或在发生溢出的时候是等效的,所以可以用异或来避免溢出一个数x可以写成二进制的相加
x = x&0x80000000 + x&0x7FFFFFFF (高1位 + 低31位)
= x&0x80000000 ^ x&0x7FFFFFFF (可以改成异或 高1位跟0异或,低31位跟0异或)所以两个数相加 (把个别加法改成异或)
x + y = (x&0x7FFFFFFF + x&0x80000000) + (y&0x7FFFFFFF + y&0x80000000)
= (x&0x7FFFFFFF + y&0x7FFFFFFF) + (x&0x80000000 + y&0x80000000)
= (x&0x7FFFFFFF + y&0x7FFFFFFF) ^ (x&0x80000000 + y&0x80000000)
= (x&0x7FFFFFFF + y&0x7FFFFFFF) ^ (x&0x80000000 ^ y&0x80000000)
= (x&0x7FFFFFFF + y&0x7FFFFFFF) ^ x&0x80000000 ^ y&0x80000000