扫盲:关于计算机,我们还应该知道些什么?

2017年,有关人工智能的新闻再次震惊世界。

《自然》杂志上发表的一篇论文显示,英国DeepMind公司研发出了“AlphaGo Zero”,它在仅输入围棋规则、未输入任何人类棋谱的情况下,通过自学,就具备了完胜“阿尔法狗”的超强棋力。

经过短短3天的自我训练,AlphaGo Zero就强势打败了此前战胜李世石的旧版AlphaGo,战绩是100:0。而经过40天的自我训练后,AlphaGo Zero又打败了AlphaGo Master版本。要知道,“Master”曾击败过世界顶尖的围棋选手,甚至包括世界排名第一的柯洁。

人类几千年的围棋成就被计算机通过40天自我训练超越。计算机的学习能力如此强大,让人不禁想要了解计算机如何一步一步进化到今天的样子。

第一台计算机:埃尼亚克

世界上第一台电子计算机“埃尼亚克”(ENIAC,即Electronic Numerical Integratorand Calculator“,电子数字积分计算机”的缩写)诞生的时间是1946年2月10日。

早在第一次世界大战期间,诺伯特·维纳(Norbert Wiener)在马里兰州的阿伯丁军械界试验场工作,参加火炮火力表测算的时候,就痛感高速自动计算手段的必要性。

1940年,美军军械部又找上门来,请维纳去阿伯丁重新制订火力表,说希特勒的战斗机速度很快,飞行员们又大耍曲线飞行、翻筋斗的特技,盟军的高射炮根本打不着他们,需要制订新的火力表。维纳认为用手工和器械算肯定不行,只有研制高速计算机。他特意给时任罗斯福总统科学顾问的万·布什写了一封信,提出设计新型电子计算机的几条原则:
不是模拟式,而是数字式;
由电子元件构成,尽量减少机械部件;
采用二进制,而不是十进制;
内部存放计算表;
在计算机内部存贮数据。

数字式的加法和乘法装置、电子管元件、二进制、自动程序运算和内部存储数据,对现代计算机的设计有着深远的影响。万·布什点头称是,于是人类历史上大名鼎鼎的高速计算机——“埃尼亚克”诞生了。

\"\"

图1:埃尼亚克 (图片来源: http://detail.zol.com.cn/picture_index_1740/index17395727.shtml

现代计算机的诞生

艾伦·麦席森·图灵(Alan Mathison Turing)的可计算性把计算问题都变成了数学计算问题。有了维纳的控制论,计算机就可以根据指令自动执行计算任务。克劳德·艾尔伍德·香农(Claude Elwood Shannon)的思想体现在模块化和等价性。他提出所有的数学问题都可以等价为逻辑运算(简单的二进制运算),而逻辑运算可以使用简单的逻辑电路单元方便地实现。

有了以上前提,就可以绕开复杂的十进制计算机的思路(巴贝奇差分机于1822年研制成功,是世界上第一台“会制表的机器”。运算的精确度达6位小数,但由于当时的技术条件限制,巴贝奇终其一生也没有完成精度更高的十进制计算机。)转而使用大量简单的逻辑电路的组合,实现与十进制计算机等价的计算。

约翰·冯·诺依曼 (John von Neumann)从织布机的“卡片”得到启示,将控制计算机的指令与数据同时放在存储器中。参加埃尼亚克研制小组后的1945年,在共同讨论的基础上,冯·诺依曼发表了一个全新的\u0026quot;存储程序通用电子计算机方案\u0026quot;–EDVAC(Electronic Discrete Variable Automatic Computer的缩写)。冯·诺依曼计算机由控制器、运算器、存储器、输入设备、输出设备五部分构成,这一结构奠定了现代计算机的体系结构理念:

  • 计算机处理的数据和指令一律用二进制数表示;
  • 顺序执行程序,即在计算机运行过程中,程序和被处理的数据首先存入主存储器(内存),计算机执行程序时,将自动地并按顺序从主存储器中取出指令一条一条地执行,这一概念称作顺序执行程序。
  • 计算机硬件由运算器、控制器、存储器、输入设备和输出设备五大部分组成。

\"\"

图2:冯·诺依曼体系结构

冯·诺依曼体系结构计算机是为逻辑和数值运算而诞生的,在数值处理方面已经达到很高的速度和精度,但对非数值数据的处理效率比较低。随着计算机体系结构研究方面进展,越来越多的非冯计算机相继出现,如光子计算机、量子计算机、神经计算机以及DNA计算机等等。

值得一提的是神经网络计算神经网络计算机,它能够模仿人类大脑的判断能力和适应能力,具有并行处理多种数据的能力,可以判断对象的性质与状态,并能采取相应的行动。

计算机思维

我们所说的计算机思维是指,了解计算机解决问题的方法,把现实世界的实际问题抽象为计算机可以解决的等价问题(等价性)。把复杂问题分解为许多模块化的小问题,解决了这些小问题,就得到了问题的解(模块化)。在云计算时代,掌握计算机思维、高效地利用计算机解决问题具有更大的优势。

下面我们就用一个例子,来说明计算机将如何解决现实世界中的问题。比如,你要安排一次旅行(旅行商问题:Travelling Salesman Problem),途经n个景点,有多少种行程安排?在计算机世界里这类问题的时间复杂是最高的,随着n取值的增加,计算复杂度随着指数方式增长,时间复杂度为O(n!)

我列举一下随着景点数增加计算复杂度的变化,你可以感受一下这个恐怖的速度:

n=3   可能路线数为:6n=6   可能路线数为:720n=8   可能路线数为:40320n=15  可能路线数为:1,207,674,368,000n=30  可能路线数为:265,252,859,812,191,058,636,308,480,000,000

当n=30结果约为2.65后面32个0,如果按照每秒计算5000个结果(埃尼亚克加法速度)需要计算1.68百万亿亿年,已经远远大于宇宙年龄的138亿年。

为了简单起见,n取值为4。我们整理一下思路,首先我们在4个景点中选择一个,然后在剩余的3个景点中选择一个,直到最后一个景点。所有的可能性为4x3x2x1=4!

这是人类的思维方式,而计算机善于使用递归方法解决问题,如果想得到4!只要知道4x3! 就可以了,如果想知道3!只要知道3x2!,类似地,需要知道2!的话,知道2x1!就可以了。我们知道1!=1,这样我们就把问题自顶向下逐步分解为简单问题,最后当遇到1!就结束递归给出结果。

递归算法实现

递归是一种优雅的问题解决方法,比如一个董事长如何管理好一个公司,使用递归方法的思路是董事长只要管理好下属的CEO、CFO等人;CEO如何管理好一个公司呢?只要管理好公司的副总就可以了;以此类推,最后每个员工管理好自己手里的工作,就解决了如何治理好一个公司的问题。这样是不是很优雅的解决方案呢?

递归算法有两个关键条件,第一是基线条件(base case)告诉程序何时停止递归。第二是递归条件(recursive case)告诉程序何时调用自己。

如前所说,计算机将指令和数据存入内存,然后按照顺序执行。计算阶乘的递归函数Python代码如:

def factorial(x):if x == 1:#基线条件   return 1else:  #递归条件return x * factorial(x-1)

如果计算机遇到一条递归令,如何执行呢?这里需要引入一个计算机编程概念:调用栈(call stack)。因为计算机顺序执行的特点,当遇到调用另外一条递归指令的时候,(x*factorial(x-1))就把这条指令放入调用栈,然后处理新的factorial(x-1)递归指令。(注意调用栈的特点是先进后出。

下面分析一下遇到factorial(4)时调用栈的变化。

\"\"

图3:处理递归指令时调用栈的变化情况

同样的方法处理factorial(3)返回递归调用factorial(2),将factorial(2)放入调用栈;处理factorial(2)返回factorial(1),将factorial(1)放入调用栈;当处理factorial(1)时返回为1,这时的调用栈的出栈处理过程如下最后返回结果为24:

\"\"

图4:调用栈出栈过程

设计模式:经典问题的解决方案

你知道什么是 GOF(“四人帮”,全拼 Gang of Four) book吗?
1994 年,由 Erich Gamma(苏黎世大学计算机博士,Eclipse项目主要技术负责人)、Richard Helm(墨尔本大学计算机博士,IBM Watson研究员)、Ralph Johnson(伊利诺伊大学教授,模式和重构领域大神) 和 John Vlissides(斯坦福大学计算机博士,IBM Watson研究员) 四人合著出版了一本名为《 Design Patterns - Elements of Reusable Object-Oriented Software 》的书(中文译名:设计模式——可复用面向对象软件的基础),这本书凝聚了软件开发界几十年经验的结晶,已经成为面向对象技术的“圣经”,对后面出现的极限编程(敏捷开发的一种方法)有着深远的影响。

书中介绍了23种设计模式,这些模式可以分为三大类:创建型模式(Creational Patterns)、结构型模式(Structural Patterns)、行为型模式(Behavioral Patterns)。设计模式并不高深,我们使用的Java语言中的MVC就是一种设计模式。通过设计模式,可以实现代码编写工作的工程化。设计模式代表了最佳实践,可以使代码更加容易增加新功能而不必改动原有代码。

设计模式的本质是在已有方案之上的渐进式重构(《重构:改善既有代码的设计》作者:\tMartin Fowler 原作名:Refactoring: Improving the Design of Existing Code),从而控制业务逻辑复杂度和代码实现复杂度。但是随着业务发展,代码的业务逻辑复杂度增加,如何控制代码的实现复杂度和相应的易理解性、可维护性和可扩展性也成了需要考虑的问题。在设计模式领域最常遇到以下两个误区:

在一开始写代码之前使用设计模式,这违背了“在已有的方案上发现更好的方案”的原则,如果没有动手写代码,何谈更好的方案呢?

使用太多设计模式。这会导致方案逻辑分层更加复杂,引入多余的接口和分层。如果业务复杂度不高,使用一个简单直接的方案就足够了。设计模式不是万能的,只有出现代码的坏味道才有必要使用设计模式。
为什么选择策略模式?
在20多种设计模式中选择一个适合的模式,的确是很困难的事情。这需要平时多练习和思考,考虑设计模式是如何解决设计问题的,研究相似的设计模式和模式之间是如何关联的。策略模式是设计模式中行为型模式类型的一种。

同时,策略模式也符合开闭原则(Open Close Principle),即在程序需要进行拓展的时候,不必修改原有的代码,实现软件特性的热插拔效果。策略模式对于解决if条件分支泛滥的问题有很好的效果。

先看一下已有的业务模型和解决方案:现在已知景点之间的路径所经历的距离、时间、和成本,而且景点个数有可能很大的情况下,我们如何选择旅行商算法呢?
穷举法,优点是实现简单,找到所有的可能路径后计算最适合路径,当然缺点是当n数量增加时复杂度呈指数级增长;
动态规划算法,会降低当n增加时的计算量,但是也不适合n过大的情况;
贪心算法,可以处理n很大的情况,但是有可能得出的是局部的最优解而不是全局最优解。
算法各有优劣,不能在设计软件时确定使用哪种算法。如何实现用户在程序运行的时候选择算法和评价策略呢?最简单的方法是使用if分支语句把所有可能的条件罗列出来,但是算法和评价策略的选择是相互耦合的,造成if分支语句泛滥。伪代码如下:

def tsp(evaluate, method):  if (method == SMALL):     if (evaluate == DISTANCE):         #穷举法实现距离最短代码     elif(evaluate == TIME):         #穷举法实现时间最短代码     elif(evaluate == MONEY):         #穷举法实现金钱最省代码  elif (method == LARGE):      if (evaluate == DISTANCE):         #动态规划算法实现距离最短代码      elif (evaluate == TIME):         #动态规划算法实现时间最短代码      elif (evaluate == MONEY):         #动态规划算法实现金钱最省代码

随着算法实现的增加和评价策略的增多,代码行数呈几何式增长。存在的一个关键问题是:很难在不改变已有代码的基础上增加新功能。因为这样会导致代码复杂性增加,难以维护。

下面是使用策略模式后,实现旅行商问题的类图。如果增加一种算法,只需要增加一个新的Strategy接口的实现类就可以了,不需要修改已有代码。而对评价原则的增加只需要实现不同的ContextInterface()接口就可以了。这样的程序风格是不是比那个又臭又长、难于增加新功能的if语句优雅了很多呢?

\"\"

总结

我们知道,计算机的设计思想发展经历了图灵的可计算性、维纳的控制论、香农的等价性和模块化,最后由冯·诺依曼提出了现在计算机的体系架构。很有趣的一个事实是,埃尼阿克的设计原则是由电子元件构成,尽量减少机械部件;而多年以后的今天,软件的设计模式(设计模式是经典问题的解决方案,可以使软件研发实现工程化)同时又参考了机械部件的特性——热插拔设计思想(开闭原则)。数十载光阴过去,计算机的发展就像是经历了一个轮回,只是一切已不再是原点。作为人类智慧成果的最佳代表,人工智能已经占据了时代的主流,人类社会生活的各大领域将继续因它而发生广泛而深刻的变化。前路漫漫,未来可期。

作者简介

万金,《DevOps实施手册:在多级IT企业中使用DevOps》译者
15年知名外企与中国企业的IT从业经验,包括IBM,华为,ThoughtWorks具有8年云计算相关经验,多系统的研发和运维经验,敏捷和DevOps专家。公众号:DevOps手册。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值