论人类下一代语言的可能—8.2现代计算机
现代计算机是通用图灵机的一种工程实现,这一工程实现可从二进制讲起。所有进制的位置记数法原理上等价,实践中不同进制的记数法有不同的适用性。一进制并不适合面向人的使用,因为符号的辨识上满足不了使用的要求。十进制提高了数字符号的辨识度,同时可与人的10个手指形成配合,从而被广泛使用。二进制制则在另外的领域表现出其适用性。二进制的发明可以追溯至莱布尼茨。莱布尼茨对二进制情有独钟,用法国数学家、物理学家拉普拉斯(Laplace,1749.3-1827.3)的话说:“莱布尼茨在他的二进位算数中看到了宇宙创始的原象。他想象1表示上帝,0表示虚无。上帝从虚无中创造出所有实物,恰如在他的数学系统中用1和0表示了……[if !supportFootnotes][i][endif]”。这暗合了二进制在现代的神奇应用之旅。
二进制是用0、1这两个数字,以及逢二进一的规则来表示自然数,进而形成二进制的算术系统。二进制的基础符号0、1,正好可对应逻辑真值:假、真,在“逻辑的探讨”章节中,布尔代数中的与、或、非运算通过真值表定义,抽象地看,二进制个位上加法运算可以看作与布尔代数同类的运算。0、1与现代电子技术里的电路与电子器件的物理特性相匹配。1、0可正好对应电路的开与关,电脉冲的有与无,电平的高与低等。利用这一特性,技术上可由继电器实现与门、或门、非门的数字逻辑电路,实现布尔代数运算。利用异或门的数字电路可以模拟出二进制的加法运算。其他的算术计算:减法、乘法、除法,逻辑上可归结为加法计算,技术上通过补码等方法,可在加法电路的基础上设计支持这些计算的电路。
0、1,形成了一个基础的对立,结合表示空间的位置,就是一个最小的编码系统。我们可以对任意信息用二进制来编码,比如英文的26个字母或中文的每个字都可以通过ASCII (American Standard Code for
Information Interchange)码或Unicode码与一个8位或16位的二进数对应。8位的二进制码,称为一个比特,是信息量的计量单位。在计算机的应用中,信息的二进制编码也称为内码。同样利用电子器件“有或无”的状态特性,我们可制造存储器以内码的形式存储信息。二进制下,符号世界与物理世界的同构,是现代计算机实现的诀窍。
人类神经系统是神经元(神经细胞)通过突触相互连接成的神经网络,单个神经元与突触工作机制也符合“有或无”的方式:输入一个信号,神经元或者激活,或者抑制;激活的神经元或者通过突触向邻近连接的神经元输出一个信号,或者不输出。这是一个刺激人工智能研究的描述,但这样概括神经元与突触的工作可能过于简化,不一定能支持起对神经网络整体复杂性的解释。
下一步的关键是提出“可存储程序计算机”的构想。这是由美籍匈牙利数学家冯·诺依曼(Von Neuman,1903.12-1957.2)等人提出的,所实现的计算机,其体系结构如下:
(图8-2,冯·诺依曼机的体系架构)
系统由存储器、运算器、控制器、输入设备和输出设备5部分组成,其工作原理是:
将程序与数据预先输入存放在存储器
控制器从存储器里逐条取出程序,解析后送入运算器执行
这里的程序是一个指令集,每一条指令可分为二个部分
[if !supportLists]· [endif]操作码
[if !supportLists]· [endif]操作数地址码
操作码对应计算机的基本操作,主要就是运算器的运算操作。操作数的地址码是存储器的一个地址,对应地址里存放有操作码要操作的数。操作码、操作数地址、地址里的操作数,所有这些最终是以二进制形式告知计算机,再转换成对应的电信号,驱动硬件运行。运算器又称算术逻辑单元ALU(Arithmetic Logic Unit),原理上就是由前面所说继电器的数字逻辑电路发展而来,所执行的就是算术四则运算与布尔逻辑运算,配套上还有移位、比较与传输操作,以及更多技术实现上的细节。今天计算机的应用遍及各行各业,所处理的问题也越来越复杂,很多领域的程序复杂度与可靠性是人类难以预测与控制的,所有这些应用中计算机所做的处理最后都是分解为算术逻辑单元的逻辑、算术计算。
冯·诺依曼等人的设计让指令可以串联起来形成程序,让机器执行多步骤的操作,这意味着所处理的问题可以足够复杂。早期的计算机执行不同类型的计算需要人工物理上重新连接机器的线路,然后才能合闸让机器运行。“可存储程序计算机”意思是存储器可放入不同的程序,通过运行不同的程序分别处理不同类型的问题,体现的正是通用图灵机的思想。
二进制的操作码与存储地址也称机器码。机器码形成了一类符号及用法,我们可用这类符号编写程序,告诉机器做什么。按本书的观点,任何符号的使用,只要复杂到一定的程度,都会追求形成系统的方法,也就是形成语言。在今天计算机技术下,形成的是程序设计语言。用程序设计语言编写程序就是此类语言的应用。用机器码编写程序。这不会是常人喜欢的工作,它识别困难、容易出错、过于枯燥。于是通过封装低级编程语言,从机器码发展出了汇编语言,再从汇编语言发展出各种高级程序设计语言。今天的高级程序设计语言不是单一门类的语言,而是面向不同用途形成种类繁多的语言。各种高级程序设计语言是人更容易理解,更接近于自然语言或数学的表示,或接近领域原生表示方式的编程语言。高级程序设计语言编写的源代码通过编译器或解释器的解析,翻译为机器可执行的机器码。
计算机是一类机器,有其实物的存在,可进行一些物理运动,如其中数字逻辑电路的运行,机器仍然需要供电来提供能量。然而计算机与之前的机器相比有很大的不同,计算机器是硬件与软件的结合,脱离了软件,裸机跟砖头没有区别。软件具体体现为各种各样的程序加数据,程序是应用各种程序设计语言通过编码实现的。传统的计算工具一直是由人一步一步地进行操作,现在计算机则是由程序驱动,自动执行并完成处理。这是一个改变世界的效果,之后的多数机器性质上都会是一台或多台计算机。这不是这里要说的重点。
图灵在构思图灵机时,也曾设想过指令集最终形成一种逻辑语言,然而今天的软件应用状况多半是图灵未曾预料到的。软件这一新物种的出现,意味着计算机器的使用可看作一个语言问题。计算机器的实际使用,机器能力与效率是需要考虑的一个方面,在给定此约束的情况下,问题的解决可以相对脱离对硬件的考虑,从软件的角度来进行,主要就是如何用程序设计语言设计实现解决问题的程序,即程序设计语言的应用问题。字面上,程序设计语言是一类人工语言,实质上,它们的内容也关联着本书的主题。
将计算机器作为符号使用主题下的一个内容来进行研究,这一说法从图灵机的起源上也是合理的。各种程序设计语言是现今最普遍在用的人工语言,我们可以独立对程序设计语言的能力进行评价。今天主流程序设计语言大多是图灵完备的,即程序设计语言可对任何可计算问题编写出程序,这已超出了逻辑学家或其它学者曾经预想过的语言,当然单独这样评价也是不完整的。在不考虑机器物理约束的情况下,学者们从抽象的角度对可计算、形式语言、算法与复杂度等问题进行研究,形成现代的计算机的理论。程序员对程序设计语言的学习,以及实际的编程工作通常也是在对硬件不那么熟悉的情况下进行的。
像自然语言一样,程序设计语言都有自己的语法。今天所有程序设计语言的语法都是基于巴斯克模式(BNF模式)或其扩展。BNF模式等价乔姆斯基的第2型文法,即上下文无关文法。前面说过,这型文法对应的自动机就是图灵机。在软件领域,乔姆斯基的形式文法是基础的理论与工具。编译器或解释器将高级语言的源代码翻译为机器可执行的机器码,同样用到乔姆斯基的理论与方法。编译器的分析会基于给定的一个文法:G=(N,∑,P,S)。首先是进行词法分析,从源代码的文本中拆分出所有的词,并标识每个词的分类。然后进行语法分析,其结果是构造出语法树。原理上,语法树的每一叶子节点对应了终结符集中的一个,每一中间节点对应了非终结符集中的一个,中间节点到下级节点会对应一个产生式规则。目标代码就是根据语法树生成。
程序告诉计算机做什么,以及怎么做。做什么是指要解决什么问题,怎么做是指问题的求解的算法。一个程序包含了解决某类型问题的一种算法,每类问题的算法通常不止一种,由不同程序设计语言针对同类型问题同一算法的表达也不完全一样。我们用程序设计语言表达对各类问题所设计出的算法,这是程序设计语言与我们说到的其他语言的主要不同。算法其实是一个古老的课题,传统上一个逻辑或数学问题被解决,也就是找到了问题求解的一种算法。不同类型的问题都需要探索性工作来寻找其算法,这是逻辑、数学研究中的一项主要工作。数学学习中大量的解题训练也包含了让学生去理解掌握各类问题算法的目的。
在手工计算操作的时代,背后是人类共通的行为,缺乏一种迫切的需要,让我们去提出“算法”的概念并用符号对其进行描述。图灵把对计算的研究回溯到计算操作及操作步骤的连接,使算法的问题突出了起来。软件出现后,用符号描述算法成为一个核心的课题,得到更多的关注与研究。算法的概念经常被延伸为各类行为中的策略,比如出行路线的规划。本书对算法的探讨限定在符号范围内:问题是符号可描述的,算法是用符号来描述的。由于技术上的原,最后的八篇只在同名公号里发布,本平台存在未审核通过的文章(即有断号),也可到那里阅读。
软件通过工程化方法实现,其中的算法是分析、设计人员设计,编程人员通过编程实现在程序里。程序设计语言对算法的描写是精确与详尽的:处理的每一步骤以及每一步骤上的处理细节;这一描述可被机器执行。程序对算法的描述,最终规定了机器的行为。也就是,目前计算机的能力表现得再强大,背后还是依赖于人的设计。这一说法目前在人工智能最新的一些领域存有争论。
[if !supportEndnotes]
[endif]
[i][i]《什么是数学》(R·柯朗 H·罗宾, 复旦大学出处社 2005年)P15页