怎么算
假设M和N都是n位的有符号二进制数,则M-N等于M+N的补码
M
−
N
=
M
+
(
2
n
−
N
)
M-N=M+(2^n-N)
M−N=M+(2n−N)
为什么可以这么算
首先,在计算机系统中取负数有三种方法
- 补码(Signed-2-Complement):取反加一
- 反码(Signed-1-Complement):取反
- 原码(Signed-Magnitude):将最高位改成1,数据位不变
上面的减法中用到的就是补码。
考虑如下情况
若
M
>
N
M>N
M>N则结果=
2
n
+
(
M
−
N
)
2^n+(M-N)
2n+(M−N)会溢出,将最高位舍弃,即减去
2
n
2^n
2n,剩下的结果就是
M
−
N
M-N
M−N,所以结果是正确的;
若
M
<
N
M<N
M<N则结果=
2
n
−
(
N
−
M
)
2^n-(N-M)
2n−(N−M),是
N
−
M
N-M
N−M的补码,即相当于
N
−
M
N-M
N−M取负数,就是
M
−
N
M-N
M−N,所以结果也是正确的。
因此减法最终也是转化为加法,可以由加法器来实现
溢出(Overflow)
产生进位不一定会产生错误的结果,比如上面的分析中的第一种情况,但如果真实的计算结果超出了n位可以表示的范围,即溢出,就会产生错误的结果,比如正数相加出现负数,负数相加出现正数。且没有进位也不代表结果一定正确。
先说结论:观察最后产生的进位和上一位(有符号数的最高位都是符号位,从上一位开始到最低位都是数据位)产生的进位,若一致则结果正确,若不一致则产生溢出。
证明: 出现溢出,只有可能负数相加或正数相加。若是正数相加,符号位都是0,最后一位相加不可能产生进位,即进位为0,溢出的话是数据位(即倒数第二位)相加产生了进位,使得符号位变成了1,成了负数,此时符号位和数据位的进位不同;若是负数相加,一定会产生进位,即进位为1,溢出的话是因为倒数第二位相加没有产生进位,使得符号位是0,变成了正数,因此结果错误,此时符号位和数据位的进位不同。
因此综合来看,只要符号位和数据位的进位相同就是正确的结果,否则结果就是错误的。