穿越计算机的迷雾
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.1 怎样用电来代表一个数字

要进行数学计算,首先要解决的问题是如何将参与计算的数送进计算机。在机械计算机的时代,人们一般是通过将一些精心制作的零件(比如算盘珠子)移动到合适的位置来做到这一点。但是,对于现代的电子计算机来说,情况则完全不同。它不是电动的——就像用电动机代替手摇脚踏,或者用电动机代替驴来推磨那样。相反,它从里到外都是电气化的,用电来表示数字,用电进行计算。听起来有些迷糊,不过不用担心,下面就来说说这事儿是怎么发生的。

通常,数学运算功能被构造成一个独立的部件。这个部件就像一个盒子,它从外面接收一些数,经过计算之后,再把结果送出来。

制造一个包括所有数学运算功能的部件固然很好,但这对刚刚翻开本书第1章的你来说显然不切合实际。最明智的做法是先制作一个小的、能完成某个简单运算的部件。当这个部件制作完成后,根据需要再进行扩充。看起来加法运算非常简单,那么我们就从制造一个加法运算部件开始吧。

鉴于我们生活在一个盒子的世界,几乎所有的电器都被做成盒子,所以,一个加法运算部件看起来就像这样(图2.1)。

图2.1 加法运算部件

因为加法运算需要一个加数和一个被加数,所以这个加法运算部件提供了a、b两个输入端,好让它知道要算的数是什么(这是理所当然的,这台机器必须由我们随心所欲地决定计算什么。如果它只能固定地计算2 + 2 = 4的话,我们为什么要制造它?这太无聊了);当这个加法运算部件完成计算后,它把结果从o端送出来。由于刚刚学习了电学知识,所以现在到了发挥你想象力的时候了:你认为应该怎样通过a和b将数据送到这个部件里?

要想把准备加起来的两个数通过a和b送到运算部件里,最自然的想法就是将不同的数表示成不同的电压。

这个想法真是太妙、太完美了!不是吗?如果我要计算20+15,我可以在a端加上20V的电压而在b端加上15V的电压,当运算完成后,o端就会有35V的电压——这正是我们所要的结果。

遗憾的是这种美好的愿望会因为一个无奈的事实而注定无法成为现实。好的设计通常都需要反复推敲,而不是靠拍脑袋产生的灵光一现。在上面的设计中,当参与运算的数都很小时,它当然可以工作得很好,但是当数字变得很大时(这是最常见的情况),情况开始变得有些微妙,比如计算99768332+112211,这意味着你得生成9000多万伏的高压。

并不是说人类无法得到这样高的电压,事实上这很容易,但是这个运算部件未必能够承受住这样的高压而不被烧毁。就算我们真能制造出这样的机器,恐怕谁也不敢靠近它,更不要说把它买回去放在家里,让几百米之外的邻居怀着恐惧的心情聆听到它“嗞嗞”的叫声。这样的计算机最好还是放在一般人到不了的地方,并在醒目的位置贴上“内有高压,请勿靠近”的标签。

如果这还能容忍的话,那么制造这样一台运算部件真正无法逾越的困难是表示像11.001 56这样的小数。通常,一个电路只能工作在近似精确的状态,因为有很多不可预知的因素会对它产生干扰。除了电路本身要消耗电能之外,像温度变化、组成电路的零件偶尔“感冒拉肚子”这样的情况也会在不适当的时候跳出来和你作对,它们都能导致整个电路的状态产生一些微小的改变。这意味着当你计算20+15的时候,尽管你从a和b送进去的是精确的20V和15V电压,从o端输出的也不可能正好是35V,可能会比它高,也可能比它低,比如34.95V。具体会是多少伏,取决于具体的情况,但总的说来这并不算是什么大事儿,因为我们知道自己计算的是整数,尽管不太准确,34.95V这个结果是我们可以接受的。

不过,麻烦在于,假如我们真的想得到一个精确的结果11.001 56时,该怎么办呢?将电压精确地调整到这个数值是非常麻烦的,而最要命的是这个运算部件根本无法保证它不会变化。如果正在进行的是金融计算,这个误差够你喝一壶的。总之,我们得换一个考虑问题的思路。

经过一段时间的思考,你可能会想到另一个办法来解决这个问题。前面的方案之所以行不通,是因为仅仅只用一根导线是不可能表示所有数的。但同时你也会发现,无论一个数有多大,它总是0、1、2、3、4、5、6、7、8、9的不同组合。比如125是1、2和5的组合;93850是9、3、8、5和0的组合,等等。有了这个发现之后,我们不再使用单独的一根导线,而是使用多根导线来表示一个数,其中每根导线都对应着这个数中的一位,如图2.2所示。

这个修改是相当成功的。在图2.2中,5根导线中的每一根分别代表着93850这个数的每一位,按从上到下的顺序。在具体应用的时候,根据这个数每一位的数值为各个导线分配相应的电压。它最大的特点就是不再使用令人畏惧的高电压,取而代之的是从0~9V的九种低电压。如果觉得以伏为单位还是太高,有点浪费的话,你也可以使用更小的电压,比如毫伏(mV)来代替,完全不影响效果。

图2.2 用多根导线来表示一个数

尽管表示像25这样的两位数只需要两根导线就足够了,但是这个世界并非只为两位数而存在。为了表示尽可能多的数,使用尽可能多的导线是必要的。比如下面这个加法运算部件,它是在图2.1的基础上修改而来的(图2.3)。

图2.3 修改后的加法运算部件

在这个例子中,数据输入端a、b已经被分别扩充为5根导线。当然,用这5根导线可以表示的数最大为99999,并不算大。如果需要,可以使用更多的导线,完全可以随你的便。

到目前为止一切都好,唯一的缺憾是没有说明它如何表示一个小数。这其实算不上是一个大问题,要表示一个小数,有多种办法可供选择。最简单、最省事儿的办法就是把导线分成两组,分别代表整数部分和小数部分(图2.4)。

图2.4 整数部分和小数部分的划分

划分的方法可以随意,比如像上图那样,把5根导线划分成3位整数部分和2位小数部分,能够表示像225.01和999.25这样的数。要是你用9根导线,就可以划分成7位整数部分和2位小数部分,或者5位整数部分和4位小数部分,等等,取决于你到底想怎么样。

这个方案能保证数据的精确度吗?答案是完全可以。现在,不管一个数有多大,也不管它是不是带有小数部分,它的每一位都对应着一根导线。这个改进非常重要,它将一个数的每一位分开,这是保证一个数据在传送和处理过程中不会发生变化的第一个重要举措。

第二条措施也同样重要。由于每一位可以是0~9中的任何一个数字,所以它意味着应当为每根导线准备十种电压(比如从0~9V)中的某一个。当然,电压可能不会十分精确,比如我们要的是7V,它可能只有6.9V,或者6.8V。不过,这对我们影响不大,我们可以规定,如果电压在6.5~7.4V之间,则认为它等于7V;如果电压在7.5~8.4V之间,则认为它等于8V,如此,等等,这样就很好地解决了精确度的问题,除非发生了比较大的电路故障(被家里有小孩儿拆个稀巴烂不算在内,但还是要引起足够的重视,因为经验教训往往需要付出一定的代价:生气、悔恨、咆哮、跺脚和咬牙切齿)。

注意,小数部分的精度和电压的精度无关。因为这仅仅是一个你认为小数数位是哪几根导线的问题,而每根导线上数的精度已经不是问题了。

万事俱备,只欠东风。这个用电来表示数的方案无论从哪个方面看都是无懈可击的,所以下一步的工作就是如何具体实现这个运算部件。换句话说,亲自动手来制造这个运算部件。

因为这个方案是你自己想出来的,所以你准备大干一场。“用它来计算加减乘除?谁会这么傻?简直是自讨苦吃。但是我还是想把它做出来,”你暗暗地想,“至少它让我觉得有成就感。我对电学还是有一些了解的,瞧好吧!”

在美美地睡了一觉之后,你迫不及待地坐到桌子前开始着手实现你的伟大计划,但这时你才发现原来自己根本没有头绪。这有点儿像一个和父母赌气的孩子,在离家出走后才发现自己根本不知道应该去哪儿。只见你一会儿苦思冥想,一会儿快速地在纸上画着什么,但是渐渐地,谁都可以明显地看出你开始有些烦躁,家人招呼你吃饭你也懒得答应,满地都是纸团儿,纸篓的大部分是空的,仅有的几个还是你最开始扔的。

一天、两天、三天,一个多星期过去了,你依然没有任何进展。刚开始着手这项工作的时候还吹着口哨,但现在已经被越来越长的叹气声所取代。最终,你决定去请教本地的一位电子技术专家,毕竟在这个领域里他们是最有发言权的。

“年轻人,”专家在听完你的讲述,认真思考了一会儿后说,“从理论上来说,你的方案是可行的。你也许听说过模拟计算机,它就是按照这种思路做成的。模拟计算机在1940年以前就有了,甚至还被安装在潜艇上,用来计算发射鱼雷时所需要的方向和速度。不过,它的用途有限,而且凭你现有的条件也许根本做不出来。你完全可以采用更好的办法,而且只用很普通的材料就可以手工实现。”

临走的时候专家送给你一本书,是关于什么是二进制的。“请认真阅读,细细体会,从现在开始,你的生活里将只有0和1。”