关于计算机中使用补码运算

1. 原码、反码、补码简单介绍

  • 原码、反码、补码都是含有一个符号位的、对带符号数的二进制表示,对应于同一个真值。
  • 原码带符号位直接读出来就是真值。
  • 正数三码合一。
  • 负数的反码为符号位不变(即保持为1),其余位取反(相反转换可用同样方法);
  • 负数的补码为符号位不变(即保持为1),其余位取反后,对末位再加1(相反转换可用同样方法)。

  进一步理解:

  原码:Sign-Magnitude。不妨以典型的8位二进制为例(未做说明的话,下同),可以将8位划分一个符号位和一个幅值区,幅值区为后7位。

  反码:Ones' Complement。常说的通过取反操作获得反码的方式,本质上来源于1的补集。-X (X为正整数)的补码,等于1111 1111减去X的8位2进制的原码表示(注意,第一个1是符号位,可参与该处所作的相减运算。因为被减数是正整数的原码,符号位为0,用1减去这个0,结果为1,所以不必仅令后7个1减去X的原码的后7位、然后首位保持1,而可以直接全8位参与相减)。 如-3的补码可这样获得:1111 1111 - 0000 0011 = 1111 1100,这和取反操作得到的结果是一致的(取反操作的话:原码1000 0011→符号位保持1不变,其余各位取反1111 1100)

  补码:Two's complement。此处的two's指的是2^8,-X (X为正整数)的原码,等于2^8减去X的8位2进制的原码表示,也即1 0000 0000-减去X的8位2进制的原码表示(注意2^8需用9位表示,且第一个1参与相减)。显然2^8比1111 1111大1,这恰好和平时说的取反加1相一致(取反加1的说法可帮助到快速计算;2^8-X的说法有利于理解补码运算是如何生效的 )。

2. 补码运算是如何生效的

  首先运算分三种:正数加正数;正数加负数;负数加负数(计算机只做加法,因为做减法的话,电子元件完成相应的物理实现需增加成本)。仅讨论加数、被加数、减数、被减数的绝对值小于等于幅值区最大值的情形,如8位2进制表示法下的127。

  1. 正加正比较简单,略去。

  2. 正加负:为了方便,将前文所说的8位二进制改作4位二进制(含首位的符号位),此时0111=7即为所能表示的最大正数。

  结果为正的情况:以5-3为例,-3的补码是 1 0000 - 0011 =1101,上述运算说明了:在1101的基础上,再加3(即0011)即可满模,即满2^4=16=1 0000,从而使后4位清0。5-3相当于(-3)+5,加5过程中,加到3时已达成满模清0,为完成加5操作,需继续再加2,完成加2操作后,该加法运算便完成了,恰得到0010,即+2的补码,便在计算机中完成了5-3=2的运算。

  结果为负的情况:以3-5为例。首先细述一遍运算过程:-5的补码是 1 0000 - 0101 =1011,(-5)+3:1011 + 0011 = 1110,1110首位为1,为负数,其绝对值所对应的原码为 1 0000 - 1110 = 0010,即绝对值为2,则1110对应于-2的补码(上述运算过程中,已先求得了结果的补码1110,在得到该补码其对应原码的过程中,使用了“ 1 0000 - 1110 = 0010”,这对应于从真值到补码的逆运算,该运算式得到的是真值的绝对值,将0010的首位的0变为1,即得到了真值-2。实际上,若采用取反加1法的话,可以更快完成原码和补码的相互转换:都是符号位不变(即保持为1),其余位取反后,对末位再加1,而取反加1法对于相互转换的有效性可以从上述运算过程中体会到)。考虑“-5的补码是 1 0000 - 0101 =1011”,显然,“1011”基础上加3后所得到的补码所对应的绝对值(因为只有负数的补码是通过上式得到的,故仅适用于1011加3后的结果小于10000情况下,不然便对应于“结果为正的情况”了),可这样得到:令“0101”减3,得到0010,即2,则结果为-2。

  “结果为正的情况”与“结果为负的情况”如何统一理解:B-A运算,总的来说,相当于用A在模(对于8位2进制,为2^8=256)上挖个洞,然后用B去填。具体地,首先令模-A,得到了-A的补码,其符号位为1。然后开始加B,(1)如果B小于A,那么模无法填满,-A的补码加上B后,相加结果小于1 0000,即小于等于1111,符号位保持为1,仍保持为负数。但是相加运算使得模更接近于填满,运算结果所对应的真值的绝对值更接近于0,负数没那么负了;且B越大,结果越没那么负,因为1 0000-(-A的补码加上B)对应于结果的绝对值的真值,B越大,结果真值的绝对值便越小,同时考虑到结果为负数,所以说没那么负了;(2)如果B大于A,那么模将填满,-A的补码加上B后,相加结果大于1 0000,即大于1111,满模溢出,使得符号位由1变为0,从而使运算结果变为正数,此时B越大,运算结果所对应的真值作为一个正数其绝对值越大;(3)可以看到,利用补码进行运算,并令符号位参与运算,能够:满模溢出时符号位变号,使得结果从负变为正;随B的增大,运算结果的绝对值先减小再增大;这符合数学认知。

  3. 负加负:1xxx + 1xxx的结果必然溢出,且结果是1 0xxx还是1 1xxx中的一种,前者表示无溢出,后者表示有溢出。至于计算机识别、处理溢出的细节和负加负运算的细节,没弄明白,故不讨论

3. 利用原码、反码进行运算的劣势

关于计算机中使用补码运算

(此处图片,截取于参考资料1)

 

 

 

参考资料:

1. 为什么计算机采用补码而不是原码或反码? - 醉卧沙场的回答 - 知乎 https://www.zhihu.com/question/352057791/answer/876413629

上一篇:Linux上通过dd命令低格硬盘


下一篇:计组——浮点数的表示和运算(考前记一记,喝前摇一摇)