第一章 实现简单需求
一般来说,学习计算机语言通常是买一本书,然后根据书中的解释写程序,编译操作,然后观察结果是否正确。第一个例子是在屏幕上打印一行Hello world.在这里,我们不想先教你如何写一个可操作的程序,而是通过引入问题和理解解决方案来理解软件是用来做什么的,以及软件可以解决什么样的问题。
人类知识的出现必然有其原因,有需求才有动力,这是市场经济和人类意识进化的规律。自从有了电脑,人类就把很多工作转移到软件上去实现,现在人们的工作和生活基本上离不开电脑。无论计算机是如何出现的,无论软件的开发过程如何,我们只解释一个简单的需求,以及如何通过现有的知识来实现它。只要你能理解一个简单的需求实现过程,你就可以通过不断的学习和实践来理解或构建一个复杂的系统。
提出问题2 3=?”,或许您会说,这个太简单了,不是问题,完全没必要通过计算机去解决,但这里我们正是要通过这个简单的问题讲解计算机怎么实现一个人看似简单的解决方法。只要我们能实现2 3然后我们可以使用计算机比人脑计算得更快123456789 23456876结果。然后计算,比如y=sin(x)、y=e x 这种函数也可以进一步构建更复杂的系统。
解决问题的方法永远不会只有一种。无论是在生活中还是在编程中,都不要把问题的解决局限在一个狭小的空间里。当问题出现时,敞开心扉,找到所有可能的方法,找到解决问题最有效的方法。如果你经历了很长时间的战场,那么你的直觉会告诉你什么方法是最有效的,所以对于不同的解决方案,只有你尝试更多,更个人的经验才能获得解决问题的直觉。例如,计算机硬件工程师首先想到的可能是通过加法器电路实现2 3=5,软件程序员更有可能写一个程序来实现解决方案2 3=5,如果需要实现计算器界面,请使用它Delphi实现起来比java要简单得多。各种技术和工具都有自己的服务目标,所以它们必须有自己的优势。使用最合适的技术和工具总是可以事半功倍。
在这里,我们不解释如何找到最合适的方法,因为每个人都有不同的知识,只有最适合自己,而不是最适合每个人。
如果你有鸡粪,你可以卖鸡粪。我经常在网上看到一些技术纠纷,比如J2EE与.NET对比平台,将Delphi与VC 相比之下,很多刚开始学习的人会问,我应该选择学习哪种语言?目前市场上需要什么编程语言?java还是程序员工资高?.net程序员工资高?事实上,无论你选择什么编程技术或工具,你只有一个目标,那就是写软件来满足客户的需求。如果你是初学者,选择你认为最容易入门的工具和编程语言。如果是因为工作需要,那么你可以选择最快解决工作问题的技术。假如你想成为一个真正的通用程序员,那么什么都学。一切都不是绝对的,如果你现在只有鸡粪,想要生存,那就卖鸡粪吧。所以我们不去争论用哪个技术来解决2 3=5是最好的。
要解决2 3=5这个问题,首先要做一些前提准备。
1.首先,2,3,5这些符号是什么?
当然,回答数字很简单。这个问题似乎不是问题。但为什么不回答数据,或者更抽象地说信息呢?在特定和概念之间总是有一种联系,即抽象,人类语言是抽象的,文本也是抽象的,抽象的过程是一种协议。
现在我们假设一个现代人遇到了一个原始人,现代人说:请给我2一个苹果,原始人肯定不明白。举这样一个例子的原因是计算机只是一个非生物体,比原始人更不智能。要让计算机解决问题,首先要让计算机和人们达成一致的认可。当我们通过语言与另一个实体交流时,我们传达2这个信号必须有一个信号载体,比如通过说话的声音,伸出两个手指的肢体语言,或者通过书写的文字2或者干脆画画2苹果。所有这些信号都存在于某个世纪的物体上。对于受体来说,如果你想理解这个信号,你必须事先与发送信号的主体达成一致,即每个符号的意义是什么。我们经常在战争电影中看到士兵用手语说:3在这里,所有士兵都事先达成了一致认可,并使用手表12点表示平面方向,方向是指以自己或对方为参考,手语表达方法等。这些在计算机领域有一个更专业的名称协议,我们将在下一章中讨论协议。
扩大协议概念的,协议=可以说一切都是协议。
现在我们要实现现在2这个数字的表达需要通过载体从上面知道人与人之间的沟通来表达。2有很多方法。但是我们现在用电路来解决问题,所以信号自然用电来表达。电是看不见的东西,所以我们应该知道2 3计算结果需要将电变成其他信号,人眼才能看到。因为我们不在乎2 3我们只对结果感兴趣,所以2和3以及“ 我们不要求法云运算的表达路能显示给我们看。这里我们暂不讨论怎么显示结果。用电来表示数字“2”,这可以有很多种方法,如通过电压表示,数字1用1V表示,数字2用2V表示,或者,用电流大小表示,1用1毫安表示,2用2毫安表示。如果采用其中任何一种方法,那么是否要表示10000,那就要用10000V或10000mA来表示呢,显然,这种方法是不可行性的。而且如果电路被干扰,那么,数据就会产生错误。
人类进行语言交流的时候,同样的26个字母或几千个汉字,但是可以表达出无穷的含义,其原理是什么,就是符号的组合。那么我们在用电路来表达信号的时候,是否也可以用信号组合的方法来表达更复杂的信号呢。那么我们觉得最简单的,而且不容易出错的方法是什么呢?就是定性而不定量,人类的认知里面,绝大多数是定性认知,而定量要涉及到计算,问题就变得复杂。所以用电的有无来表示信号,变得简单又可靠。
但是怎样将信息用电的有无来表示,最开始也有很多的探索,这个就是信息编码学的范畴,我们在这里并不去具体追究。在计算机领域我们最终采用了来表达信息。
我们知道,电这个物质有两个描述量:电压和电流。
那么是用电压的有无来表示信号好,还是电流表示信号好呢?通常的情况是这样的,由于只要有电流通过,就必然有功率损耗,但是有电压并不一定就有功率损失,因为电路断开的时候灯是熄的就不用耗电,这点好理解。那是不是所有电路的信号表示就只用电压表示呢,也有信号传输过程中就采用电流的有无来表示0和1。
这里提到二进制,就同一起了解下。
我们来看数字表示的约定:
10进制 |
2进制 |
16进制 |
8进制 |
2 |
10 |
2 |
2 |
8 |
1000 |
8 |
10 |
16 |
10000 |
10 |
20 |
10 |
1010 |
A |
12 |
3 |
11 |
3 |
3 |
5 |
101 |
5 |
5 |
“2”是一个我们通常在语言中使用的10进制数,10进制我们好理解。对于二进制,2=1+1,满2就必须进1,同十进制的满10必须进1一样的道理,所以第2位的1表示的大小是第1位乘上2,即1x2=2,第三位呢,就表示第二位乘上2,即2x2=4, 这就如100=10X10一样。将10换成2就是一样的。所以第8位就是2 x 2 x 2 x 2 x 2 x 2 x2(7个2相乘),我们用指数表示就是27,可以看到,第n位就是2的n-1次方。
我们来看常见的计算机的8位二进制数,就是用8位来表示信号。
全部为1时就是11111111,变成10进制数就是
11111111=27+26+25+24+23+21+20=128+64+32+16+8+4+2+1=255
如果再加1,那么所有位均产生进位,就全部变成0了,在程序中有个概念叫“溢出”。
那么一个8位数能表示多少个不同的信号,是255个么,可不要忘了0也是一个信号哦,因此可以表示256个信号,这正好是28。所以n位二进制数就可以表示2的n次方个不同的符号,由于长度是没有限制的,如果不够用,我们可以用更长的位数来表示不同的信号组合,在人类语言中,我们说话的长短是没有规定的,有时就一个字,有时可能是很长一段话。但是不管怎样,我们的文字基本符号的个数是有限的,而且并不是很多。我们是通过文字的组合来表达一个含义,用英语,也不是用字母的组合来表达一个含义,而是用更高级符号组合即单词(word)来表达一个含义,而汉字也不是用笔划来组合表达一个含义,而是首先用笔划来组合成汉字,然后用汉字来表达一个含义。计算机是对于人类沟通信息领域的一种模拟,所以必然遵从一样的规律。我们并不直接用0和1这两个二进制符号来表达一个复杂的含义,而是首先将0和1组合成一个有意义的基本符号,然后再进行表达。
我们用多少位来表示一个基本符号呢,2位?肯定太少,表示不了几个符号。100位?似乎太多,就如我们不会造10万个汉字去书写一样,太多,要在人与人之间沟通反而变得更难。需要花很多时间达成一致的符号理解。
如果仅仅表示0-9这几个10进制数字,需要多少个符号呢?10个,那么需要多少位二进制来表示10个符号呢,答案就是4位可以表示16个不同的符号。
基本符号 |
2进制表示 |
符号组合 |
2进制 |
0 |
0000 |
12 将12看成是一个
|
是用1100表示么, 不是,否则又回到原来的用0和1表示所有的含义的状态了。 |
1 |
|||
2 |
0010 |
||
3 |
136 注意这里将136看成是一个,而不是仅仅是一个数字,因为我们要解决更通用性的需求。 |
这里十进制数“136”是由三个更基本的符号组成的“1”、“3”、“6”所以,我们在计算机中也用代表基本符号的二进制组合表示 “”“”“” 1 3 6 这里暂不讨论最终3个符号组合在计算机中怎么存储。 |
|
4 |
0100 |
||
5 |
0101 |
||
6 |
|||
7 |
0111 |
||
8 |
1000 |
||
9 |
1001 |
||
|
1010-1111没有用到 |
||
假设我们要用到x、y、z这三个符号,并利用上面4位二进制中余下的组合来表示它们 |
|||
x |
1011 |
3z z5y zyz x88yzzz 可以有无穷组合, 每个组合我们可以给他们定义不同的含义。 |
每个组合,我们用4位二进制的组合表示,与上面类似。 |
y |
1100 |
||
z |
1101 |
通过上面数字符号与一般符号的组合对比,可以看到,数字的无穷性就是一个符号组合的无穷性。
关于信号的编码也是一门专业的学科,作为程序员可以不去追究目前计算机为什么采用这些信息编码格式的原因,但是也至少应该清楚编码的实际含义以及采用这些编码的好处。如果读者对于信息的编码和存储感兴趣,可以自己去更加深入地学习,或许你会在某些领域找到一些更加有效的信息编码方法,让计算变得更快,让存储空间占用更小。 |
上面讲了二进制是什么,其他进制的原理也基本一样。只有在16进制中,出现了符号“A、B、C、D、E、F”分别代表10进制的“10、11、12、13、14、15”,为什么要这样,0-9这几个数字符号与10进制一样,都可以用对应的阿拉伯数字可以表示,因此与10进制共用这些数字符号,但是超过10时,没有相应的阿拉伯数字对应,因此必须用其他符号来表示,而且是单一的符号,而不是组合符号。这样就产生了用“A”来表示10,为什么不用其他符号来表示,这仅是一个约定俗成,并没有其他的含义。如果最初制定这个规则的人,心血来潮用“O、P、Q、R、S、T”来表示一样也是可以的,但是人类的思维总是应该遵从一定的规律,A属于字母排序中的第一位,自然而然地就优先被采用了。
从二进制的表示符号来看,仅包含“0”和“1”,而且任意长度符号组合又可表示无穷多的含义,因此采用二进制来表示信息,不仅可以满足要求,而且让实现变得更加简单可靠。只要用电的有无来表示0和1就可以实现对所有信息的表示。
当然,在计算机领域,对于信号的表达也并不仅采用电信号,任何可以转化成电信号的载体均可以用来承载信息,如我们常见的光盘、磁盘。但是可以说,在计算机领域,数字化的信号表达基本是采用二进制来存储和传输的。
而二进制似乎有长度规定,一般取8位、16位、32位、64位。关于这一点,其实只是因为计算机中表示信息是采用8的整数倍个位来表示,并不是二进制的规定。二进制与十进制一样可以表示任何的有理数。但是二进制可操作性似乎比十进制差,这一点又是一个错觉,我们现在接触的阿拉伯数字0到9,是一个外来品,我们觉得它好记数,是因为我们从小就习惯了它,以致于我们的程序员,在看到一个二进制或16进制的计算时,总是要先转换成10进制才能口算。如果你与老人聊天,或许听说过,我们国家以前的称重量的称是16两一斤的(所谓半斤八两),也就是说是16进制计数的。所以,对于数制,习惯成自然,没有什么先进不先进之分。
再回到2+3=5的问题上来,我们清楚了二进制的概念,那么我们,用二进制来表达下这个需求吧
10b + 11b = 101b
注意,上试中的每个数字后面用了一个字符“b”,表示是一个二进制表示的数。这也是一个约定俗成。没有什么特别含义,因为我们在写程序的时候,在C语言,汇编中常常采用这样的书写规范,编译器就会知道这是一个二进制数。同样在每个数字前面加上“0x”表示一个16进制数。如0x2+0x3=0x5。
注意信息被编码存储在存储介质上后,并不会指明编码本身的含义,就如我们单独把一个字母拿出来看的时候,并没有确切的含义,如一个8位的二进制数1100001b,你可以解释成是一个整数“97”,也可以解释成一个字母“a”。因此对于信号的编码来说,其本身并没有意义,而是使用的人赋予了它含义,这就如文字本身并没有什么意义,而是我们的约定俗成让语言有了具体的含义。 |
为什么程序员要了解二进制的概念,为什么要学习关于计算机的符号表达方法,似乎我们可以什么都不用了解,只要写个程序就解决问题,又何必在这里啰嗦呢?如果你仅仅满足于用现有的知识解决有限的问题,当然就没必要去了解计算机更基础的内部运作原理。但是那样,你可能因为某个程序语言的退出市场而失业,或者因为技术的更新换代而疲于奔命地学习新技术。如果我们理解事情的起因,解决方法,那么即使技术的再怎么日新月异,其基本的思维方式是不变的,学习新的东西自然就变得简单了。
我们首先并不讲解怎样通过计算机的高级程序语言来解决问题,我首先讲解从底层硬件怎么解决问题。经济是政治的基础,硬件是软件的基础,似乎世界就是类似的,这就是哲学。政治与经济的发展是互相作用的,而软件与硬件的发展也是从来分不开的。一个好的工程师,往往需要同时了解硬件和软件两个方面的内容。当把软件固化到硬件中的时候,你也很难划分硬件与软件的界限。而一些知识你也无法简单地划归到硬件知识还是软件知识,就如上面讲到的关于信息编码的一些概念。
我们用一个简单的电路来实现2+3=5,至于加法器电路怎么实现,那需要读者去了解电子电路中关于数字电路的原理部分,如果你有的好奇心很强,你可以一直向更基本的物理规律去追究,如从加法器向下探索,就会涉及到逻辑电路的实现,如触发器、稳态、暂态等诸多的概念,而再向下探索就可以涉及到三极管、电容等电子元件的原理与特性,如果你的好奇心还想探个究竟,就会涉及到原子结构及相互作用的相关理论,不够一般也就了解到电子的运动规律为止,对于量子物理,我想跟你理解计算机的运作和编写程序没有太多关系。
我们做10进制计算时的有效方法就是列一个计算式:
12345
+ 235
----------
= 12580
按照位对齐,从个位开始计算。
那么二进制的2+3=5也应该可以采用同样的方法
10
+ 11
------------
= 101
一样采用位对齐,从低位开始计算,进位方式似同十进制。
那么我们是否可以采用一个类似的电路来实现呢
在这里上传比较费力,有兴趣还是直接到百度文库中看吧。
http://wenku.baidu.com/view/e05b8573f46527d3240ce0bb.html