负数表示来由 – 补码的设计思想

早早就在CS基础中熟稔补码转换规则,但对补码系统为什么这么设计一知半解,今天开一文做探讨,欢迎批评指正,转载请注明出处

补码设计目的

统一加减法,使得CPU复用加法器硬件

补码设计思想

补码其实利用的是模运算系统的“周期性”,替换自变量而函数对应关系不变

\scriptsize
f(x)=f(x+T)\\
f(x-a)=f[x+(T-a)]\\
n位二进制系统是模2^n系统,其中T=2^n

这样 -aT-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.
百度百科 – 补码 计算机中有符号数的表示方法

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

©2018-2024 Howell版权所有 备案号:冀ICP备19000576号