前言:
《人人都懂计算机》系列博客的目的是让没有接触过计算机,或者对计算机的认识仅停留在会上网、打游戏和看电影等水平的人,能够知道计算机是什么,它的工作原理是什么。本系列博客尽量做到通俗易懂和深入浅出,同时也兼顾学术严谨,因而难免会出现一些相对专业的术语,读者如果对某些术语不是很了解,大可不必在意,这些术语完全不影响对内容的理解。
第二章 :0和1的世界
很多人觉得程序员捣鼓的东西很复杂,普通人搞不懂。而事实上,程序员的世界比普通人的更简单,因为程序员的眼里只有0和1,而普通人的世界里除了0和1之外,还有有2、3、4、5、6、7、8、9。接下来就让我们一起走进程序员0和1的世界。
2.1 进制的概念
所谓“进制”,实际上只是人们用来计数的一种方法。现实生活中,我们天天都在使用的由0到9组成的数字就属于“十进制”。对此,大家早就习以为常,但接下来我们将换个角度来看待十进制,进而认识十进制的本质。
2.2 十进制
在十进制中,从右(低)到左(高)依次是个位、十位、百位……,而且每一位都是0~9这十个数码(符号) 中的一个。十进制下的任意一个数都可以表示成这十个基本符号的组合。之所以称为十进制,是因为在计数的时候,每当最高位的值超过9就必须再增加一位来表示,即“逢十进一”。为了更好地理解十进制,我们将一个十进制的浮点数 123.45用科学计数法表示成如下形式:
123.45=1×102+2×101+3×100+4×10−1+5×10−2(2.1)
在上式中,我们将123.45的每一位分别用该位的符号i(i=0,1,...,9)乘以该位的权重(个位的权重为100,十位的权重为101,依次类推;小数点后第一位的权重为10−1,第二位的权重为10−2,依次类推),而浮点数的值恰好是这些乘积的和。由此我们得出结论:十进制就是用0到9这十个互不相同的基本符号,通过多位数的形式来计数,高位和相邻低位之间存在十倍的关系。这就是十进制的本质。
2.3 二进制
认识了十进制之后,再理解二进制就会容易很多。不过,在正式介绍二进制之前,我们还需要先讨论一下为什么计算机会使用二进制而不是十进制。在生活中,十进制我们用得那么舒服,为什么程序员却偏偏选择了二进制呢?
2.3.1 计算机为何采用二进制
这个问题的答案,会随着你对计算机软硬件了解的不断深入而不断完善,本书只给出几个主要的原因,读者也可以在此基础上分析出更多的原因。尽管现在的计算机好像无所不能,但实际上,它数数的能力和上幼儿园时的我们差不多。还记得上幼儿园的时候学习数数吗?一开始,我们都是借助十个手指头来完成的。老师让我们数3,我们就伸出3根手指;老师让我们数5,我们就伸出5根手指;老师向你伸出4根手指,你就对老师喊4……当时的我们,没有去思考这意味着什么。实际上,我们的十根手指代表了十一种(包括伸出0根到10根手指这11种情况)可以相互区分的手势(状态),或者说十一种互不相同的符号。当时的我们很自然地将这十一种手势和数字0到10一一对应了起来。
类似地,如果计算机也采用十进制来计数的话,那么它也需要一种具有十种互不相同状态的元件,就像上幼儿园时的我们需要十根手指一样。这样的元件存在么?遗憾的是目前还没有找到。现今计算机芯片中大量集成使用的晶体管 (包括二极管、三极管、场效应管等,这些元件都是利用半导体材料制成,其中半导体是一种导电性介于导体和绝缘体之间的材料,其导电能力在制造成元器件时可以人为控制。),都只能处于两种状态:导通和不导通。这和我们平时使用的电灯开关是类似(实际上这两种情形还是有差别的:晶体管利用的是其自身的单向导通性,而电灯开关则是将电路断开)的:按一下开关,电路导通,于是电灯亮了;再按一下开关,电路断开,于是电灯灭了。计算机就是用晶体管(实际中用来记录0和1的不只是一个晶体管,而是由包括晶体管、电容和电感等组成的基本电路单元,如SRAM、DRAM等)的导通和不导通这两种状态来分别代表0和1的 。事实上,元件的“二态性”限制是计算机采用二进制的最主要原因。看到这里,你可能会疑惑:一个晶体管只能表示0和1,那比1更大的数呢?很简单:将两个相互独立的晶体管并排起来,则这两个晶体管就可以表示00、01、10和11这四种状态。如果再将这四种状态和0、1、2、3一一对应,这是不是就意味着两个并排的晶体管可以表示任何小于4的正整数了呢?类似地,如果将三个晶体管并排起来,则能表示的状态就更多,再通过一一对应,能表示的数字也就更大。计算机内存(组成计算机的不同硬件存储0和1的原理并不相同,比如硬盘就利用了磁铁的南极和北极来存储0和1。但这些硬件无一例外都利用了某种元件的二态性。其它相关硬件的存储原理本书后续会逐步介绍)就是通过这样的方式来计数的。
另外,除了电路只有导通和不导通这两种状态之外,生活中还有很多只有两种对立状态的情形:真与假、对与错、白天和黑夜、电流的正向与反向、磁铁的南极与北极等等,这些情形使用0和1来表示显然比十进制更合适。于是有学者在这类情形的基础上,建立了一套完善的理论,即逻辑代数。逻辑代数是二进制运算的理论基础。
再有,因为二进制只有0和1这两个符号,所以二进制的加法、减法、乘法和除法运算比十进制更简单,具体原因本章后续会更详细地介绍。
最后一点也很重要:二进制的抗干扰性比十进制更强。我们知道,计算机内部使用的是弱电(在电工领域,电力分为强电和弱电,其中弱电的直流电压一般在36V以内,强电则在36V以上)。以CMOS(CMOS有多重含义,这里指受电压控制的一种放大器件,是组成CMOS数字集成电路的基本单元)为例,它的正常电压范围是0V~5V。如果采用十进制,那么需要将5V等分成十份,即0.5V表示1,1V表示2,以此类推。假设现在计算机保存了数字“3”,那么它对应的电压就应该是1.5V。这时,如果电压一不小心升高了0.5V,这个数字就变成了4,就出错了。而如果采用二进制的话,由于二进制只有高(对应1)和低(对应0)两种电压取值,我们可以以2.5V为界,就算电压发生一定程度的变化,仍然容易分辨出电压的高低,从而避免出错。