美文网首页
编码:实现减法

编码:实现减法

作者: 汪小鱼 | 来源:发表于2021-10-19 07:34 被阅读0次

    1 前言

      本文是基于《编码》、《穿越计算机的迷雾》两部著作进行读后整理的记录性博客。对书中较为重要的内容进行归纳整理进行二次创作,略去了繁琐的讲述细节,力求简明扼要。


    编码:一种由若干符号和规则组成的系统,用来向计算机表述指令。

    2 正文

    2.1 如何实现减法

      加法和减法在某些方面相互补充,但在机制方面这两个运算则是不同的。加法是始终从两个加数的最右列向最左列进行计算的。每一列的进位加到下一列中。在减法中没有进位,而是有借位——一种与加法存在本质区别的麻烦机制。

      要解决这个问题,首先从最右列着手。我们看到,6 是大于 3 的,因此从 5 上借 1,再用 13 减去 6,得到结果为 7。由于我们已经在 5 上借了 1,因此,现在实际上那一位是 4,而 4 是小于 7 的,因此继续从 2 上借 1,14 减 7 结果为 7。而由于在 2 上借了 1,实际上这一位是 1,从中减去 1,结果为 0。因此,最后的结果应为 77。

      如何才能通过一连串逻辑门来实现这个反逻辑呢?

      然而,我们并不打算这样做。相反,我们打算用一个小技巧来让减法不涉及借位。为了避免借位,首先要从 999 中减去减数,而不是从原来的被减数中减去减数。从一串 9 中减去一个数叫做对 9 求补数。176 对 9 的补数是 823。

      计算出减数对 9 的补数后,将补数与原来的被减数相加:

      最后再将结果加 1,并减去 1000。

      到此,我们就得到了结果。答案与先前的相同,而且没有用到借位。

      我们按照前面的步骤梳理一下计算过程。原题目是这样的:
    253-176

      这个式子于下面的式子等价:
    253+(999-176)+1-1000

      我们用两个减法和两个加法来替代一个减法,而在这个过程中避免了烦琐的借位。

      如果减数大于被减数会怎么样呢?例如以下问题:

      如果希望求解这个问题而不使用借位的话,就要采用与之前稍微不同的方法。首先要像前面一样,用 999 减去减数 253,计算出对 9 的补数:

      把该数对 9 的补数与被减数相加:

      在前面的例子中,下一步应该加 1,并减去 1000 来得到最终结果。但是在这里,这种方法并不适用。因为你会遇到 923 减去 1000 的情况,这又导致了借位。由于我们之前已经加了 999,这里再减去 999:

      到这里,我们会意识到这个问题的结果是负数,因此需要将减数与被减数交换,用 999 减去 922(也即改成 999 - 922,结果加上负号)。这里没有用到借位,结果与我们期望的相同:

      同样我们来回顾总结一下上述的计算过程。原题目是这样的:
    176-253

      这个式子于下面的式子等价:
    999-253+176-999

      同样的技巧可以用于二进制数中,而且实际上这要比十进制数简单。

    实际上这上面介绍的针对减法的用于避免借位的计算技巧主要是保持计算过程中永远是对位最大的数(999)减去小的数,这样的话在相减的过程中就避免了要向前面借位,可以直接减掉。而由于是十进制下所以对位最大的数是 9,利用对位最大数去减去任何数都不涉及借位的操作。而对于二进制下,对位最大的数是 1,也即计算出该数在二进制下对 1 的补数。111 在二进制下的作用就相当于十进制下的 999。

      将上面提到的 254 - 176 转化为二进制数进行计算,那么问题变为:

      同样的,求补数:

      在求对 1 的补数时,只需将原来的二进制数中的 1 变为 0,将 0 变为 1 即可。因此对 1 求补数有时也会称为相反数(negation)或反码(inverse)。在前面的内容中我们介绍过反向器,它的作用就是将 0 变为 1,将 1 变为 0。

      将减数对 1 的补数与被减数相加:

      将上式所得结果加 1,减去 100000000(即 256):

      我们把这两个数颠倒位置后再做一遍。在十进制中,减法题目对应于 176 - 253。而用二进制表示为:

      计算过程如下,最后计算结果加上负号:

      了解了上述计算技巧后,我们可以开始尝试实现一下减法的操作。下面构建的减法器适用于计算结果为正数的减法操作。

      针对求补数的计算过程,二进制数对1求补数相当于对其每位取反,因此我们可以利用反向器来实现相应的操作。以 8 为二进制减法为例,我们计算 8 位二进制数补数的时候可以简单地应用 8 个反向器。

      问题是,该电路只会对输入求反,而我们要的是一台既能做加法又能做减法的机器,因此就要求该电路当且仅当进行减法运算时才实现反转。电路可以改造为如下图所示。

      标记为 “取反” 的信号将被输入到每一个异或门中。回想一下异或门的工作方式,如下表所示。

      因此,如果 “取反” 信号是 0,则 8 个异或门输出与输入相同。例如,如果输入是 01100001,那么输出也为 01100001。如果 “取反” 信号为 1,则输出信号反置。例如,如果输入为 01100001,输出则为 10011110。

      将 8 个异或门合并起来画成一个器件,称为求补器(One’sComplement),如下所示。

      将一个求补器,一个 8 位二进制加法器和一个异或门做如下连接。

      注意,这里三个信号都标识为 “SUB”,这就是加/减法转换开关。当该信号为 0 的时候,其进行的是加法运算,为 1 时进行的则是减法运算。在减法中,输入 B(第二排开关)在送入加法器之前,需先通过求补电路进行取反。此外,在做减法时,我们通过设定 CI(进位输入)为 1 来使得结果加 1。而在加法中,求补电路将不起作用,且输入 CI 为 0。

      加法器的 SUB 信号和 CO(进位输出)输出作为异或门的输入来控制表示上溢/下溢的灯泡。如果 SUB 信号为 0(表示进行加法运算),则当加法器 CO 输出为 1 时灯亮,意思是加法计算结果大于 255。

      当进行减法运算的时候,如果减数(输入 B)小于被减数(输入 A),这时加法器的 CO 输出为 1。这表示减法的最后一步要减去 100000000。也就是说减数要大于被减数,结果为负。上面所示器件现在还不能表示负数。因此,上溢/下溢指示灯仅在加法器的 CO 输出为 0 时才会亮起。


    3 小结

      编码:实现减法篇对二进制加法器部分进行了拓展,讨论了如何利用全加器实现了二进制的减法操作。为了精简内容删减了部分较为详细的书写,仅作为整理总结。

    相关文章

      网友评论

          本文标题:编码:实现减法

          本文链接:https://www.haomeiwen.com/subject/fwdwoltx.html