为什么我们需要补码

补码的产生和硬件的设计脱离不了干系,当然这也是为什么在硬件课上才会讲这个的原因。

这里我们阐述一下问题,以及它的背景
问题:我们要做一个能做加法和减法的计算器,但是要能用电子器件做。
限制:
1、这个计算器要元器件尽可能的少,不然太多散热不行
2、物理上,电子器件的基础操作非常简单,粗略的理解就是只能看有电没电,也只能做有电到没电,或者没电到有电的转换。
3、数学上,由于电子器件的基本操作的限制,那么由他所构成的数学运算得基于二进制,而且只能将就着进行一些基本的位运算(移位,与或非)

解决办法1:
这里我们很直白的使用一个符号位表示正负,用剩下的表示数值。然后再做一个加法器,一个减法器。
这样做很简洁直白,但是问题也非常多,比如:
(1)一个加法器,一个减法器,零件太多,散热不行,而且也没法做小
(2)要分的情况太多,正数+正数,负数+负数,正数-正数,负数-负数,而且这些都得先看了符号位,再看大小才能进行下一步,步骤太多,拖累整体运算速度。
比如,正数-正数,要先看这两者大小,然后才能决定结果的正负。负数-负数同理

解决办法2:
这里也不知道从哪里捡起来的东西解决的,不过总之这里有个很神奇的方法可以优化。
(这里只是叙述这个方法为什么有效,至于这个方法是怎么从灵感一步一步变化到真正的解决办法,我还真没有看到过。如果有人来补充,都很欢迎)
1、A-B=A+(-B)
2、同模之下,一个数等于它加上模数,那么

(A-B)mod M = (A-B+M)modM
3 - 2 mod 5 = (3-2+5)mod 5 = 6 mod 5 = 1

4、使用2进制表述法时,计算机都有限制过电路最大支持位数n,但是我们还得再表示正负,那么就得拿出来最开头的1位来表示正负,剩下n-1位表示数的绝对值。
同时结合前面的取模运算,这里2的n次方可以视为电路数学里的模数M。

5、在二进制下,以2的n次方为模时,负数的补码,可以这么计算-110 1100的补码

[-110 1100] = 1 0000 0000 - 110 1100
= 1000 000 + 1000 000 - 110 1100
= 1000 000 + (111 1111 - 110 1100) + 1
= (1000 000 + 001 0011 + 1 )mod (1 0000 0000)
= 1001 0100
这么麻烦的步骤,我们直接看结论,粗暴的优化下来的话,负数的补码就是:符号位不动,剩下的位数取反再+1。

6、整个流程数下来,我们做的就是,拿来一个负数,符号位不动,剩下取反再+1,然后跟另一个任意数相加,就得到结果了。
整个过程用到的只有加法,还有取反操作,这样就可以用加法器模拟减法器了。省心又省力
当然这里会有溢出现象,这种现象是由于得到的结果超过mod 模数上限,所以得到的只有截断之后剩下的部分。对于这个,硬件会再加一根信号线表述溢出的。

这里的讲解,只是从另一个更让我容易理解的角度接受了补码。它并没有启发我,也没有告诉我补码这么复杂的东西,它最开始的灵感是什么更加简约的东西,所以后面我会想办法再考证补充一下它的灵感来源。

posted @ 2021-01-27 22:38  lylofe  阅读(84)  评论(0编辑  收藏  举报