数学中最简单的就是加法和减法。然而在计算机中,最简单的运算却是AND、OR和NOT。
物理课上,我们都做过串联实验。把两个开关依次连起来之后,如果还要点亮灯泡,就必须同时闭合两个开关。
将开关闭合定义为1,开关断开定义为0;将灯泡点亮定义为1,灯泡熄灭定义为0。则串联的两个开关与灯泡的关联规则是:
( 0 and 0 ) -> 0
( 1 and 0 ) -> 0
( 0 and 1 ) -> 0
( 1 and 1 ) -> 1
这个规则与布尔代数中的AND操作规则完全一致。
( 0 AND 0 ) -> 0
( 1 AND 0 ) -> 0
( 0 AND 1 ) -> 0
( 1 AND 1 ) -> 1
于是,将串联的开关作为输入,将灯泡的亮灭作为输出,上面的电路久构成了计算机中AND操作(与门)的基本结构。当然计算机的与门没有这么简单,实际上是通过两个继电器(或缓冲器)来实现的,只是基本原理如此。与门的符号如下:
提到串联自然会想到并联。把两个开关并联起来,如果还要点亮灯泡,闭合任何一个开关就可以。
同样的定义,开关断开闭合与灯泡亮灭的规则为:
( 0 or 0 ) -> 0
( 1 or 0 ) -> 1
( 0 or 1 ) -> 1
( 1 or 1 ) -> 1
这个规则与布尔代数中的OR操作规则完全一致。
( 0 OR 0 ) -> 0
( 1 OR 0 ) -> 1
( 0 OR 1 ) -> 1
( 1 OR 1 ) -> 1
于是,并联开关的电路图就构成了计算机中OR操作(或门)的基本结构。当然,计算机实际上还是通过两个继电器(或缓冲器)来实现的。或门的符号为:
除去串联和并联,还有一种电路连接方式,叫做短路。
上面的连接方式中,当开关断开,灯泡点亮;当开关闭合,灯泡熄灭。其关联规则为:
( 0 ) -> 1
( 1 ) -> 0
这正是NOT运算符的运算规则。与AND、OR都需要两个输入不同,NOT运算符的输入只有一个。
( NOT 0 ) -> 1
( NOT 1 ) -> 0
计算机中实现NOT运算符的电路叫做反转器,也就是将输入的信号取反输出。和与门、或门都需要两个继电器操作两个输入不同,反转器的实现只需要一个继电器。反转器的符号为:
前面的AND、OR和NOT三个运算符之间是可以组合的。如果反转器跟在与门的输出之后,就构成了“与非门”,其符号如下。
“与非门”的运算规则就是将与门的输出反转。
( 0 NAND 0 ) -> 1
( 1 NAND 0 ) -> 1
( 0 NAND 1 ) -> 1
( 1 NAND 1 ) -> 0
同理,如果反转器跟在或门的输出之后,就构成了“或非门”,其符号如下:
“或非门”的运算规则,就是将或门的输出反转。
( 0 NOR 0 ) -> 1
( 1 NOR 0 ) -> 0
( 0 NOR 1 ) -> 0
( 1 NOR 1 ) -> 0
“与非门”和“或非门”都是需要两个继电器。
布尔代数中的AND、OR和NOT三个运算符,以及NAND、NOR两个运算符,是计算机可以通过继电器的电路连接久可以直接实现的。那通过这五个基本运算符,可以实现数学中最普通的加法运算么?
首先,我们看一下加法的运算规则。
( 0 + 0 ) -> 0
( 1 + 0 ) -> 1
( 0 + 1 ) -> 1
( 1 + 1 ) -> 10
我们把这个规则拆分成两个部分:“进位”与“求和”。
进位
- ( 0 … 0 ) -> 0
- ( 1 … 0 ) -> 0
- ( 0 … 1 ) -> 0
- ( 1 … 1 ) -> 1求和
- ( 0 … 0 ) -> 0
- ( 1 … 0 ) -> 1
- ( 0 … 1 ) -> 1
- ( 1 … 1 ) -> 0
仔细分析下进位的规则,会发现其与AND操作的规则完全一致。因此,通过一个实现AND操作的“与门”,就能实现加法中进位的处理。
进位
- ( 0 … 0 ) -> 0
- ( 1 … 0 ) -> 0
- ( 0 … 1 ) -> 0
- ( 1 … 1 ) -> 1与门
- ( 0 AND 0 ) -> 0
- ( 1 AND 0 ) -> 0
- ( 0 AND 1 ) -> 0
- ( 1 AND 1 ) -> 1
再来看看求和的规则,可以看出这个规则与前面提到的几个规则都不一致。
求和
- ( 0 … 0 ) -> 0
- ( 1 … 0 ) -> 1
- ( 0 … 1 ) -> 1
- ( 1 … 1 ) -> 0
但我们可以通过前述规则的组合来实现:将一个“与非门”和一个“或门”分别作为“与门”的输入,看看运算结果:
(( 0 NAND 0 ) AND ( 0 OR 0 ))
-> ( 1 AND 0 ) -> 0
(( 1 NAND 0 ) AND ( 1 OR 0 ))
-> ( 1 AND 0 ) -> 1
(( 0 NAND 1 ) AND ( 0 OR 1 ))
-> ( 1 AND 1 ) -> 1
(( 1 NAND 1 ) AND ( 1 OR 1 ))
-> ( 0 AND 1 ) -> 0
这个运算的结果与“求和”的规则完全一致。
因此,我们可以通过“与非门”、“或门”和“与门”的组合,来实现计算机加法中求和的处理。其电路图如下:
对于这样复杂的基本操作,我们给它起了一个简单的名字:异或(XOR)。哈,好熟悉的名字!这个玄妙奇异的操作符,居然是从加法中诞生的。异或的符号如下:
现在我们吧进位和求和两部分操作合并起来,就可以得到如下进行加法运算的电路图。
这个电路被称为“半加器(Half Adder)”,因为这里只有两个加数的输入,还没有考虑到更低位进行加法时提供的进位。
要实现一个完整的支持多个输入的全加器,我们还要把低位提供的进位作为第三个输入,加入我们的计算器中,
根据加法规则,我们将之前计算后的“求和”部分加上更低位的进位,这同样会产生一个进位和一个求和的结果。
啊哈,现在有两个进位要处理了。如果同时为1,岂不是要继续进位。
Note:来分析下“两个进位都为1”的可能性。
先假设两个运算的进位均为1。
既然第二次运算的进位为1,就意味着低位进位和前一次运算结果的求和这两个数值必然都为1.
而根据假设条件,第一次运算结果的进位也为1。
那就是说,第一次运算的结果中,进位、求和都是一。
这是不符合加法规则的。所以,假设不成立。
舒了一口气,好在两个进位不可能同时为1。因此,我们最终计算出来的进位结果,应该是这两次进位的或操作(只要有一个进位为1,进位结果就是1)。再给这两个进位进行一次OR操作,加上一个“或门”吧。
这张图被称为“全加器(Full Adder)”,它在计算机中通过硬件实现了数学中最最基本的操作:加法。
好了,总结一下。
一个“与门”需要两个继电器
一个“或门”需要两个继电器
一个“反转器”需要一个继电器
一个“与非门”需要两个继电器
一个“异或”需要六个继电器
一个“半加门”需要八个继电器
一个“全加门”需要十八个继电器
如果要计算八位数相加的电路,就需要一百四十四个继电器!
继电器实在是太大了。幸运的事,随着技术进步,继电器早已经不在电脑中使用了。世界上的第一台电脑ENIAC就将继电器换成了真空管,可仍然占用了170平方米的空间。现在我们身边的电脑,都是用晶体管代替了真空管,但计算原理仍然保持一致。计算八位数相加,仍然需要一百四十四个晶体管。