在十进制减法中,比如 253 - 176 ,如果按照常规思路来做减法,肯定会涉及到借位,但是如果想通过一连串的逻辑门来实现这个借位的逻辑基本不可能。所以这里换一种思路,避免在减法中借位, 具体原理就是利用在减法后面加一个数减一个数结果不变,具体这个数是什么和进制有关 。
比如上面 253 - 176 做减法的过程如下:
通过上面的步骤我们没有通过借位而得到了正确的结果。其实原理很简单,式子的变化过程如下:
最终结果是我们用两个减法和两个加法来替代一个减法,在这个过程中避免了繁琐的借位。
如果被减数小于减数又不一样,比如 176 - 253 。基本思路就是将减数与被减速交换执行减法,然后给结果取一个反。计算步骤如下:
最后需要加个负号。通过上面的步骤同样避免了借位
如果出现了在二进制中出现了被减数小于减数呢。
同样用 176 - 253 举例子
在二进制的减法中,取补码是一个非常重要的过程。可以简单的用八个反向器实现。但是我们是做一台既可以做加法也能做减法的机器。因此需要让电流控制取反。 可以通过异或门实现。联想一下异或门的真值表
当一侧输入为1的时候,刚好输出结果取反。对应电流如下:
八个异或门合并起来的器件叫做求补器。符号如下:
这里输入为0则把数据直接输出,为1才取反。
将一个求补器,一个8位二进制加法器和一个异或门做如下连接。
注意这里有是三个信号都标识为 SUB ,代表加/减转换开关。当信号为0的时候就是做加法,为1就是做减法。
说各个SUB的含义
虽然现在还没有解决减法如何实现的问题。得解决负数在二进制中如何表示。
在十进制中表示负数的方法如下: ...-1000, -999 ,... -1, 0, 1, 999, 1000 好处在于能表示所有的正数和负数。将0视为无限延伸序列的重点,正数沿着一个方向,负数沿着一个方向。
但是我们并不需要无限大或者无限小的数,比如我们一开始就知道这个数的范围。
比如用5000表示-5000,5001表示-4999, ...., 9999表示-1,0001表示1, 0002 表示2,4999表示4999。
-5000,-4999,-4998,...,-1,1,2,4998,4999 5000, 5001, 5002,...,9999,0001,0002,...,4998,4999 这就形成了一个循环排序,最小负数5000看起来像最大正数4999的延续。这里的9999是比0小1的数。加上1得到10000。由于处理的是四位数,这个结果实际上就是0000.
这种方式叫做10的补数表示法。(为了简化问题这里用三位数了)将三位负数转为10的补数,再用999减去他再加1。也就是10求补数就是对9求补数在加1。 比如-255对10求补,用999减去255加1得到745。这个745就表示-255 。
同样的可以把这种机制运用到二进制中,被称作为2的补数。这里以8位二进制位例,范围是0000 0000 到1111 1111。对应十进制中的0到255。如果还想表示负数,则以1开头的每个八位数都表示一个负数。
现在表述数的范围是-128到127,最高位作为符号位,1表示负数,0表示正数。
为了求2的补数,需要先计算1的补数然后再加1。这个步骤和求10的补数一样。等价于将每一位取反然后加1。
现在可以自由的将正数和负数相加了,将-127和124等价的二进制相加。1000 0001 + 0111 1100等于1111 1101等于十进制的-3。
注意:涉及到上溢和下溢的情况,比如125+125= 1111 1010 由于最高位为1,结果表示负数了。相当于十进制-6了。
一般来讲,在加法中。两个操作数符号相同,而结果符号与操作数的符号不同,这样的加法无效。
至此,计算中二进制的加法与减法的实现介绍完毕了。当初看似复杂的东西,多看几遍也就不复杂了。探索计算机底层仍在继续......