用P表示正数,N表示负数
- P+P=P 没溢出,例如:1 + 2 =3,0000 0001 + 0000 0002 = 0000 0003,和的符号位与加数符号位相同。
- P+P=N 溢出,例如:127 + 7 = 130,0111 1111 + 0000 0111 = 10000110(-122),和的符号位与加数符号位不同。
- N+N=N 没溢出,例如:-8 + -9 = -17,1111 1000 + 1111 0111 = 1110 1111,和的符号位与加数符号位相同。
- N+N=P 溢出,例如:-127 + (-7) = -134,1000 0001 + 1111 1001 = 0111 1010(122),和的符号位与加数符号位不同。
- P+N=P 没溢出,一正一负相加肯定不会溢出。
- P+N=N 没溢出,一正一负相加肯定不会溢出。
总结一下,可以得出.若(A+B)与A同号或与B同号,就说明A+B没有产生溢出。
有符号整数的补码,如果最高位是1,表示负数。
异或的性质是,同为0,异为1。即 0 ^ 0 = 0,1 ^ 1 = 0,0 ^ 1 = 1。
所以x和a异号的话,则其最高位一定是不同的,所以x^a的最高位一定是1.
也就是如果x和a异号,则(x^a)<0,如果同号,则(x^a)>=0。
结合之前的结论,我们使用异或的结果来判断是否同号,就可以知道是否产生了溢出。
摘自guava中的一段代码。
// a与b相加
long naiveSum = a + b;
- (a ^ b) < 0,如果 a ^ b 为负数,小于零,即二进制表示的时候首位是1。则 a 与 b 异号,不可能溢出,直接返回。
- (a ^ naiveSum) >= 0,如果 a ^ b 大于或等于零,即 a 与 b 同号,可能会产生溢出。a ^ nativeSum >=0 ,则表示“和”与 a 同号,也与 b 同号,0 ^ 0 = 0 或 1 ^ 1 = 0,由前面推理可知,不会溢出。直接返回。
Long.MAX_VALUE + ((naiveSum >>> (Long.SIZE - 1)) ^ 1)
= Long.MAX_VALUE + ((naiveSum >>> 63) ^ 1)
如果 nativeSum 是正的,无符号右移63位之后, 0 ^ 1 = 1,返回的是long类型的最小值。
如果 nativeSum 是负的,无符号右移63位之后,1 ^ 1 = 0,返回的是 Long.MAX_VALUE。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。