早早就在CS基础中熟稔补码转换规则,但对补码系统为什么这么设计一知半解,今天开一文做探讨,欢迎批评指正,转载请注明出处
补码设计目的
统一加减法,使得CPU复用加法器硬件
补码设计思想
补码其实利用的是模运算系统的“周期性”,替换自变量而函数对应关系不变
\scriptsize
f(x)=f(x+T)\\
f(x-a)=f[x+(T-a)]\\
n位二进制系统是模2^n系统,其中T=2^n
这样 -a 用 T-a 替换后,运算依然正确,却将 减法转化为等效的加法
这就是“补”的意思,将可以补为一个周期的正数原码作为负数的二进制补码表示
\scriptsize
[负数]_{补码} = [周期-对应正数]_{原码}
最经典的例子是钟表,
模12系统中倒拨8点和正拨4点,结果是正确且相同的
意味着可以互换:把-8用+4表示就将减法转化为了加法
\scriptsize x-8=x+(12-8)
按照这个思想,模8系统的补码表示如下表
原码真值 | 补码 | 模系统转换 | 补码真值 |
---|---|---|---|
0 | 000 | 0=0 | 0 |
1 | 001 | 1=1 | 1 |
2 | 010 | 2=2 | 2 |
3 | 011 | 3=3 | 3 |
4 | 100 | -4=+(8-4)=4 | -4 |
5 | 101 | -3=+(8-3)=5 | -3 |
6 | 110 | -2=+(8-2)=6 | -2 |
7 | 111 | -1=+(8-1)=7 | -1 |
为什么 2+5=7 的运算规则在转换后仍适用于 2-3=-1 呢?
因为函数对应关系不变,只是将自变量替换为上个周期的值
\scriptsize
周期函数f(x)=x \mod T,有f(a)=f(a-T)\\
那么有f(5)=f(-3),f(7)=f(-1)\\
f(2)+f(5)=f(7) \Leftrightarrow f(2)+f(-3)=f(-1)加法运算仍然成立\\
即有 2+5=7 \Leftrightarrow 2-3=-1
解释负数补码“取反加一”
按照模运算系统的算法,最简单的负数补码计算方法是
\scriptsize
[-a]_{补码} = [2^n - a]_{原码}
上述方法中
1 周期超过了位数表示范围
2 用到了减法运算
这就需要利用运算性质进行转化
\scriptsize
例如模8运算系统中仅有3位二进制数,表示范围为[000]_B-[111]_B\\
但是负数补码 [-a]_{补码} = [1000]_B - [a]_{原码},[1000]_B占用了4位且有减法运算\\
利用反码性质 [a]_{原码} + \sim [a]_{原码} = [111]_B进行转化:\\
[-a]_{补码} = [001]_B + [111]_B - [a]_{原码} = \sim [a]_{原码} + 1
由此推导出 负数补码 = 对应的正数原码取反 + 1
参考资料
Randal E.Bryant, David O’Hallaron. Computer Systems: A Programmer’s Perspective[M]. 3. 机械工业出版社, 2016.
百度百科 – 补码 计算机中有符号数的表示方法