减法器

复习

  1. 第四章:基本逻辑门(与或非三门)是计算机处理二进制信号的基本单元
  2. 第五章:由基础逻辑门(与或非三门)搭建了更复杂的逻辑门:异或门,同或门,多路选择器
  3. 第六章:设计完成了半加器,可以完成两个一位二进制数的加法,但不能处理来自低位的进位
  4. 第七章:设计完成了加法器,可以处理三个输入(两个加数和一个进位),并可以串联构成多位加法器
  5. 第八章:掌握了原码、反码和补码的概念,理解了补码可以统一加减法运算

TL;DR

  • 减法可以转换为加上一个负数
  • 负数用补码表示,可以直接参与加法运算
  • 减法器实际上就是加法器,只是参加运算的数字需要先转换成补码

正文

引言

  回顾一下,减法可以转换为加上一个负数: A - B = A + (-B)

  而负数在计算机中用补码表示。所以减法的步骤是:

  1. 将参加运算的数字转换为补码(负数需要求补,而因为正数补码为自身,维持原样即可)
  2. 用加法器进行加法运算

具体实现

  以 4 位二进制数为例,计算 5 - 3:

  1. 首先,将 -3 转换为补码(5 为正数,补码为自身):

    • 3 的原码:0011
    • 按位取反:1100(反码)
    • 加 1:1101(补码)
  2. 然后,用加法器计算 5 + (-3):

      0101  (+5)
    + 1101  (-3 的补码)
    -------
      0010  (+2)
    

  结果正确——可以用加法器来完成减法运算。

减法器的构成

  从上面的分析可以看出,减法器需要以下部件:

  1. 取反器:对被减数进行按位取反
  • 可以用非门实现
  1. 加一电路:在取反后加 1
  • 可以用半加器或加法器(Cin 永远置为 0)实现
  1. 加法器:进行最终的加法运算

    • 直接使用之前设计的加法器

    或者我们也可以说: 减法在二进制计算机里的定义是,加上 减数取反后的数值,再加一。

  这些部件组合在一起,就构成了完整的减法器。

思考题 1

  可能有细心的读者发现了:A - B,只有 B 经过了求补模块,如果 A 也是负数,需要经过求补模块吗?更进一步,既然 A 和 B 都是补码了,那 对一个数的补码再求补码,等于该数的原码吗?

更复杂的例子

  来看一个更复杂的例子,计算 7 - 12:

  1. 将 -12 转换为补码(4 位二进制不够,需要扩展到 8 位):

    • 12 的原码:0000 1100
    • 按位取反:1111 0011(反码)
    • 加 1:1111 0100(补码)
  2. 用加法器计算 7 + (-12):

      0000 0111  (+7)
    + 1111 0100  (-12 的补码)
    ------------
      1111 1011  (-5 的补码)
    

  结果是补码形式的 -5,如果需要转换回十进制:

  • 减去 1:1111 1010(反码)
  • 除符号位按位取反:1000 0101(原码)
  • 符号位为 1,所以是负数:-5

思考题 2

  如果计算 -128 - 1 会发生什么?

其他减法器思路

  回想一下,半加器和加法器怎样制造的?先画出真值表,再观察能用什么逻辑门实现效果。其实减法器也可以这么做。

  下面是半减器的真值表。

ABB outD
0000
0111
1001
1100
  • 默认为 A - B
  • 输出 B out 意为 Borrow out,借位的输出
  • 输出 D 意为 Difference,差值
  • 如果 B out 为 1,肯定意味着不够减,结果为负

  当然我们也可以画成下面这样,不使用异或门,只使用与门和或门。

  但是这个图很容易就把人看晕了,跟上面的图一比较,完全不如上图清晰明了。使用异或门还可以跟真值表形成明显的对照。

  在计算机科学里,没有什么问题是加一层解决不了的 。该抽象简化的时候,就应该抽象和简化。

  下面是全减器的真值表。

ABB inB outD
00000
00111
01011
01110
10001
10100
11000
11110
  • 默认为 A - B
  • 输入 B in 与上同理
  • 输出 D 意为 Difference,差值
  • 这个可能有些复杂,给出化简后的表达式,然后拼接逻辑门
    • D = A ⊕ B ⊕ Bin(⊕为异或的数学符号)
    • Bout = AB + ABin + BBin

小结

知识点

  • 减法转换为加法的原理
  • 减法器的基本构成
  • 补码在减法中的应用

参考资料

  1. Wikipedia(zh):算术溢出:溢出的详细介绍
  2. Wikipedia(zh):补码:补码的详细介绍

思考题答案(仅供参考)

思考题 1

  我们在谈论补码的时候,有两种性质一样的说法:

  1. 减法在二进制计算机里的定义是:加上 减数取反后的数值,再加一。
  2. 减去一个数,等于加上这个数的相反数。

  所以为什么 A - B 中被减数 A 不需要经过求补模块,也可以用这两种说法对应解答:

  1. 因为 A 和 B 本身就是补码,而只有减数 B 前面有减号,所以只需要让 B 求补,同理,如果形式变成 - A - B,则需要让 A 和 B 同时求补(虽说变成 -(A + B) 会更简单一些)。
  2. 减去 B 也等于加上 B 的相反数。而之前说过,补码是从相反数相加等于零推导出来的,所以,减去 B 也等于加上 (0 - B),也就等于求 B 的相反数,也就是直接求补。

  回想一下,补码究竟是怎样推导出来的——相反数相加为零。所以,对一个数的补码再求补码,其实就是对一个数的相反数再求相反数,其结果必然等于自身。

  二进制中,特殊在于:

  • 减法的定义为:加上 该数取反后的数值,再加一
  • 负数的定义为:该数取反后的数值,再加一

  这两种说法本质上是相同的:- X,可以是 X 的负数,也可以是 0 减去 X。 有趣的地方在于:

  • 如果我们将 X 按照定义进行两次求补,也即 ~(~X + 1) + 1,它并不等于 X + ~1 + 1

思考题 2

  计算 -128 - 1:

  1. -128 的补码:1000 0000
  2. -1 的补码:1111 1111
  3. 相加结果:(1)0111 1111
    • 最高位的进位被丢弃
    • 结果是 0111 1111,表示 +127
    • 这就是溢出(Overflow)
    • 在 8 位补码系统中,-128 是最小值,再减就会溢出到最大值 +127

推荐

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪