做减法实际上也可以列出一个减法表
减 | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
(异或门)
借位 | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 1 | 0 |
(对被减数加个反向器 再与减数连个与门)
如此而来也可以一步步搭建出全减器,但如果全减器与全加器的构造法类似,从低位开始减,那么被减数小的时候便会一直向高位借位直到借完为止,如此显然不行。全减器的电路应是另一种构造,但不是本文所讨论的。
CODE以及一般计算机组成中通过使用加法实现减法。
目录
负数的表示
在讨论减法之前,我们得先探讨一下不使用负号,二进制中负数该如何表示?
一种方法是在每个数据前加一位“符号位”,但是数据量一大时,这样的储存方式就会显得臃肿,甚至在某些情况下(比如正负数相加时)带来很大的不方便。
另一种方法则是确定数据的范围,用上溢的正数代替负数。
-以八位二进制数为例-
二进制数 | 十进制数 | 二进制数 | 十进制数 |
---|---|---|---|
10000000 | -128 | 00000000 | 0 |
10000001 | -127 | 00000001 | 1 |
…… | …… | …… | …… |
11111110 | -2 | 01111110 | 126 |
11111111 | -1 | 01111111 | 127 |
在之后的学习中我们会看到,这种表示将会为我们带来极大的便利
用加法做减法
补数
一个巧妙的方法是利用补数,补数即使该数每一位取到最大值与该数的差,例如:
100在十进制下的补数就是899(999-100=899)
100在二进制下的补数就是011 (111-100=011)
又是由于二进制的神奇特性,二进制数的补数其实就是按位取反!!!
利用补数做减法
那么仅看相应的位数我们可以得出这样的等式
被减数-减数 = 差 “=” 被减数+减数的补数+1-“1max”
如 253-176 = 77 = 253 + 999 -176 + 1 (-1000)=(10)77(-1000)=77
而当遇到减数更大的情况时,比如
176-253 = -77 = 176+999-253+1(-1000) = 923(-1000)=-77
等式仍然成立;
确实,所谓的用加法实现减法从理论上看并没有完全放弃减法,只是把减法限定为了-1000或者说-1max。但是在真正的实现过程中,-1000确确实实被省略了,这多出来的1作为符号位表示上下溢,如此达到了加法器做减法的目的。
如上述的两个减法,第一个结果为1077,表示为1(零上)077,第二个结果为0923,表示为0(零下)923,而在计算机二进制中负数的表示并非加个-号即可,我们完全可以通过一定的约定表明0923实际上是-77,而1923才是+923。
比如
之前所讨论的负数表示方法,让我们用二进制再做一次176-523:
10110000(十进制176)- 11111101(十进制253)
= 10110000 + 00000010(按位取反求补)+ 1
= 10110011(对照上表对应的十进制数即为-77)
减法的实现
以下是求补器的实现(每个输入都和取反输入接入异或门)
当取反信号输入为1时,八位输出即为八位输入的补数,取反信号为0时,八位输出不变。封装后如下
改进后的加法器
三个sub表示的是同一个输入,输入为1是表示进行减法运算,输入为0时进行加法运算
又是多说几句
没错,如果使用上述讨论的负数表示法,减法其实可以不再需要,所有的运算都将是加法,所以在计算机的架构中,实际上看不到减法器(即使是上述的伪减法器)的出现。但是多看点总是没有坏处的2333。