加法器是有两种基本逻辑门电路:异或门、与门电路组成的
加法是最基本的算术运算。所以,如果想要建造一台计算机(这是本书隐含讨论的问题),
必须首先知道如何构造一种机器,它可以把两个数加起来。当你解决了这个问题,你会发现
加法正是计算机唯一所做的事情,因为通过使用用于加法的机器,我们还可以构造用加法来
实现减法、乘法、除法以及计算房产抵押款、引导向火星发射卫星、下棋和电话计费等等功
能的机器。
同现代的计算器和计算机比起来,本章构造的加法机庞大、笨重、速度慢且噪声大。但
有意思的是构成它的部件完全是前几章学过的电子设备,如开关、灯泡、电线、电池以及可
构成几种逻辑门的继电器。这个加法机包含的所有部件都于1 2 0年以前就已发明,而且,我们
并不用真正地在屋子里建造它,只需在纸上和脑子里构造这台机器就行了。
这个加法机只能工作于二进制数,而且它缺少很多现代计算机(器)的辅助设备。它不
能用键盘来敲入你想加的数,代之的你只能用一系列开关表示待加的数。它也不能用显示器
显示结果,你所看到的只是一排灯泡。
但这台加法机确实实现了两数相加的功能,而且其工作方式和计算机做加法十分相似。
二进制加法与十进制加法很像。当你相加十进制数如2 4 5和6 7 3时,你把问题分解成简单
的步骤,每一步只对一对十进制数字相加。本例中,第1步是把5和3加起来。生活中,你若能
记住加法表,问题的解决就快多了。
十进制加法和二进制加法的一大区别是二进制数字的加法表要比十进制数字的加法表简
单得多:
+ 0 1
0 0 1
1 1 1 0
你可能在学校里记过上面这张表,并背诵过如下口诀:
0加0等于0,
0加1等于1,
1加0等于1,
1加1等于0,进1。
把相加结果的数前加上零,可以把加法表改写成如下形式:
+ 0 1
0 0 0 0 1
1 0 1 1 0
这样一来,二进制数字相加的结果是两位数,分别称为“和”和“进位”(比如“ 1加1等
于0,进位是1”)。现在,可以把这张二进制加法表分成两张表,第1张是表示“和”的表:
+和0 1
0 0 1
1 1 0
第2张是表示“进位”的表:
+进位0 1
0 0 0
1 0 1
以这种方式来看待二进制加法就很方便了,因为加法机会分开求和与进位。构造二进制
加法机需要设计一个能执行表中所描述操作的电路。因为电路的所有部件,如开关、灯泡、
电线都是可以表示成二进制数的,因而该电路由于仅工作于二进制数从而大大降低了电路的
复杂性。
与十进制加法一样,二进制加法也从最右边的一列开始,逐列相加两个数:
注意,当从右边加到第3列的时候,产生了一个进位。同样的情况也发生在第6、7、8列。
我们要加多大的数呢?由于这个加法机只是在脑子里构造,因而可以加很长的数字。为
更合理一些,选择不超过8位的二进制数。也就是说,操作数的范围是从0 0 0 0 - 0 0 0 0~1111 -
1111,即十进制的0~2 5 5。两个8位二进制数的和最大可以是1 - 1111 - 111 0,即5 1 0。
当你看到下面两个1位二进制数相加的进位表时,你可能立刻会想到逻辑门和二进制加法
之间有某种联系:
+进位0 1
0 0 0
1 0 1
你也许已意识到这和上章所述的与门的输出是一样的:
A N D 0 1
0 0 0
1 0 1
所以,与门可以用来计算两个1位进制数位相加得到的进位。
看来我们已取得一点儿进展了,下一步就要看看有没有继电器能完成下面的工作:
+和0 1
0 0 1
1 1 0
这是二进制加法运算中的另一半问题,虽说表示和的这一位不如进位那么容易实现,但
我们会有办法。
首先应意识到或门的输出和我们所期望的很近似,只是右下角的结果不同:
O R 0 1
0 0 1
1 1 1
而对于与非门而言,除了左上角的输出不同以外,其他结果也与期望的一样:
N A N D 0 1
0 1 1
1 1 0
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package logic; /** * * @author Administrator */ public abstract class LogicGates { /** * 逻辑与门电路 * @param a * @param b * @return */ public static byte AND(byte a,byte b){ if(a==1 && b==1){ return 1; } return 0; } /** * 逻辑或门电路 * @param a * @param b * @return */ public static byte OR(byte a,byte b){ if(a==1 || b==1){ return 1; } return 0; } /** * 逻辑或门电路 * @param a * @param b * @return */ public static byte XOR(byte a,byte b){ if(a==b){ return 0; } return 1; } /** * 逻辑非门 * @param b * @return */ public static byte NOT(byte b){ if(b==1){ return 0; } return 1; } /** * 逻辑与非门 * @param b * @return */ public static byte NAND(byte a,byte b){ if(b==1 && a==1){ return 0; } return 1; } /** * 逻辑缓冲器 * @param b * @return */ public static byte BUFFER(byte b){ return b; } /** * 逻辑或非门 * @param b * @return */ public static byte NOR(byte a,byte b){ if(b==0 && a==0){ return 1; } return 0; } public static void main(String[] args){ byte a=1; byte b= LogicGates.AND((byte)1, (byte)0); } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package logic; /** * * @author Administrator */ public abstract class Utils { /** * * 只可以是0和1 * @param a * @param b */ public static void validate(byte a,byte b){ if((a!=0 && a!=1)|| (b!=0 && b!=1)){ throw new RuntimeException("非法参数"); } } /** * * 只可以是0和1 * @param a * @param b */ public static void validate(byte b){ if( b!=0 && b!=1){ throw new RuntimeException("非法参数"); } } /** * 打印 */ public static void print(byte[] b){ for(int i=0;i<b.length;i++){ System.out.print(b[i]); } System.out.println(); } }
/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package logic; /** * * @author Administrator */ public abstract class Adder { /** * 半加器 * @return */ public static byte[] HalfAdder(byte a,byte b){ Utils.validate(a,b); return new byte[]{LogicGates.AND(a, b),LogicGates.XOR(a, b)}; } /** * 全加器 * @return */ public static byte[] FullAdder(byte a,byte b,byte ci){ Utils.validate(a,b); Utils.validate(ci); byte fs=LogicGates.XOR(a, b); byte sco=LogicGates.AND(fs, ci); return new byte[]{LogicGates.OR(sco, LogicGates.AND(a, b)),LogicGates.XOR(fs, ci)}; } /** * 八位全加器 * @param a * @param b * @return */ public static byte[] EightAdder(byte[] a,byte[] b){ if(a==null || a.length!=8){ throw new RuntimeException("非法参数"); } if(b==null || b.length!=8){ throw new RuntimeException("非法参数"); } byte[] resu=new byte[8]; byte[] temp=null; byte ci=0; for(int i=7;i>=0;i--){ Utils.validate(a[i],b[i]); temp=FullAdder(a[i],b[i],ci); ci=temp[0]; resu[i]=temp[1]; } return resu; } public static void main(String [] args ){ Utils.print( Adder.EightAdder(new byte[]{0,0,0,0,1,1,0,1}, new byte[]{0,0,0,0,1,0,0,1})); } }