当前位置: 首页 > 新闻 > 信息荟萃
编号:4677
改变未来的九大算法.pdf
http://www.100md.com 2020年4月16日
第1页
第17页
第26页
第37页
第154页

    参见附件(7918KB,302页)。

     改变未来的九大算法,这是一本非计算机专业也能看懂的书籍,书中一共分为了九大章节内容,读者可以在这里了解一些算法的核心介绍,帮助你能够分析未来形势。

    介绍

    《改变未来的九大算法》是一本科普读物,作者致力于将计算机科学的复杂思想为大众做深入浅出的解读。此书通过简明的语言和生动的例证,阐述了计算机王国的核心算法:搜索引擎、PageRank、公钥加密、纠错码、图形识别、数据压缩、数据库、数字签名等。在解释这些算法的同时,作者也向我们展示了充满科学原创精神的计算机世界:每一种算法的提出不但拓展了虚拟世界的领域,它同时也是人类智慧的彰显,可以被广泛运用于众多领域,以推动商业和社会文明的发展。

    图书作者信息

    约翰·麦考密克(John MacCormick),计算机科学的领头人和导师。牛津大学博士,曾在惠普和微软从事研究工作。现任迪金森学院计算机学科的教授。多项所有者。

    目录预览

    前言 计算机日常运用的卓越思想

    第一章 搜索引擎索引—在世界上最大的草垛中寻针

    第二章 PageRank-—让谷歌腾飞的技术

    第三章 公钥加密——用明信片传输秘密

    第四章 纠错码——自纠正的错误

    第五章 图形识别——从经验中学习

    第六章 数据压缩—有益无害

    第七章 数据库——追求一致性的征程

    第八章 数字签名——这个软件究竟由谁编写

    第九章 并非万能的算法—有些程序不可能存在

    结语 更多在你指尖的“精灵”

    该书精彩评论

    1、长久以来,没有哪本书能让我像十几岁时阅读霍金和费曼的书时那样让我兴奋,而这本书做到了,它提醒我为什么我喜欢计算机科学。

    2、作者用日常类比巧妙地解读核心算法,这对没有数学背景的读者来说很有用。想钻研算法的数学和计算机科学的学生也会感到受益颇深……这本书应该被图书馆珍藏。

    3、计算机专业人士和非专业人士都会对这本书感兴趣。作者并没有试图“用科学迷惑我们”,也没有“卖弄”其数学才能。相反,他采用了我们都能理解的简单类比。比如,作者用混合彩色颜料来类比公钥密码的原理,这非常精彩。

    改变未来的九大算法截图

    改变未来的九大算法

    [美]约翰·麦考密克 著

    管策 译

    中信出版集团目录

    所获赞誉

    序

    前言 计算机日常运用的卓越思想

    第一章 搜索引擎索引 ——在世界上最大的草垛中寻针

    第二章 PageRank ——让谷歌腾飞的技术

    第三章 公钥加密 ——用明信片传输秘密

    第四章 纠错码 ——自纠正的错误

    第五章 图形识别 ——从经验中学习

    第六章 数据压缩 ——有益无害

    第七章 数据库 ——追求一致性的征程

    第八章 数字签名 ——这个软件究竟由谁编写

    第九章 并非万能的算法 ——有些程序不可能存在

    结语 更多在你指尖的“精灵”注释

    致谢所获赞誉

    荣获美国出版商协会“2012年计算机与信息科学最佳专业

    学术图书奖”

    作者解释了数亿人每天使用的一些算法,不是如算术和排

    序这类简单的算法,而是更复杂的事情——如何确定网页的重

    要性,以及无法被计算的问题。我强烈推荐这本书。

    ——查克·塞克(Chuck Thacker),“图灵奖”得主

    长久以来,没有哪本书能让我像十几岁时阅读霍金和费曼

    的书时那样让我兴奋,而这本书做到了,它提醒了我,为什么

    我喜欢计算机科学。

    ——安德鲁·菲茨吉本(Andrew Fitzgibbon),“艾美奖”得主(相机软件开发者)

    作者揭示了计算机科学家对算法着迷的原因:它们如此实

    用、美观和优雅。

    ——保罗·柯曾(Paul Curzon),《科学》(Science)一本关于关键算法的指南,阅读起来愉悦且轻松。它传达

    出一种奇妙的感觉——让电脑发挥魔力的是美丽的科学,而非

    技术。

    ——安德烈亚斯·特拉辛格(Andreas Trabesinger),《自然物理学》(Nature Physics)

    尽管人们对计算机充满兴趣,但并不了解其核心思想。这

    本书在向大众展示计算机科学这一艰巨的任务中取得了非凡的

    成就。

    ——欧内斯特·戴维斯(Ernest Davis),SIAM News(美国工业和应用数学学会的新闻期刊)

    大多数人对电子支付的安全性,或者电影如何被“塞

    进”光盘知之甚少,也不太关心,但作者认为它们富含惊人的

    独创性和创造力。

    ——罗伯特·马修斯(Robert Matthews),《BBC聚焦》(BBC Focus,英国一本关于科学和技术的月刊)

    作者用日常类比巧妙地解读核心算法,这对没有数学背景

    的读者来说很有用。想钻研算法的数学和计算机科学的学生也

    会感到受益颇深……这本书应该被图书馆珍藏。

    ——阿特·吉特尔曼(Art Gittleman),就职于美国数学协会(MAA)计算机专业人士和非专业人士都会对这本书感兴趣。作者

    并没有试图“用科学迷惑我们”,也没有“卖弄”其数学才

    能。相反,他采用了我们都能理解的简单类比。比如,作者用

    混合彩色颜料来类比公钥密码的原理,这非常精彩。

    ——克莱夫·马克斯菲尔德(Clive Maxfield),《电子工程时报》(EE Times)

    这本书适合对信息系统的工作原理感兴趣的人。

    ——约翰·吉尔比(John Gilbey),就职于泰晤士高等教育出版社(Times Higher Education)序

    计算机行业正在改变我们的社会,正如物理学和化学在前

    两个世纪给社会带来的巨大改变一样。的确,数字技术几乎影

    响甚至颠覆了我们生活的方方面面。鉴于计算机行业对现代社

    会的重要性,人们对让这一切成为可能的基本概念却知之甚

    少,这显得有点儿自相矛盾。对这些概念的研究是计算机科学

    的核心,而麦考密克的这本新书则是向大众展示这些概念的少

    数书籍之一。

    人们较少视计算机科学为一门学科,其中一个原因是,高

    中极少开设计算机科学这门课程。虽然人们通常认为要强制开

    设物理学和化学这两门基础课程,但作为独立学科的计算机科

    学,却通常只在大学阶段才被开设。况且,学校讲授的“计算

    机”或“信息与通信技术”知识,通常只是略高于使用软件的

    技能训练。因此,学生们认为计算机学科枯燥也并不意外;而

    他们在娱乐和通信上使用计算机技术的天然热情,也因为实现

    这类技术的学术深度而有所消退。这些问题被认为是导致过去

    10年大学计算机科学专业学生人数下降一半的主要原因。考虑

    到数字技术对现代社会的极度重要性,让人们重新领略计算机

    科学的奇妙之处已经刻不容缓。

    2008年,我很荣幸地被选为第180届英国皇家科学院圣

    诞讲座(Royal Institution Christmas Lectures)的演讲人,该讲座由迈克尔·法拉第(Michael Faraday)于1826

    年发起。2008年圣诞讲座的主题首次涉及计算机科学。在准

    备这些讲座时,我花了很多时间来思考如何向大众解释计算

    机科学,却发现能提供解决这一需求问题的资源很少,几乎

    没有关于计算机科学的畅销书。因此,我特别高兴能看到麦

    考密克的这本书。

    麦考密克在面向大众介绍计算机科学的复杂思想方面做得

    非常好。这其中的许多思想极其新颖,仅从这点上来看,它们

    就很值得关注。举个例子:电子商务的爆炸式增长之所以成为

    可能,是因为它具备了能在互联网上秘密、安全地发送机密信

    息(如信用卡卡号)的能力。数十年来,建立在“开放”通道

    上的保密通信被认为是一个科学难题。当人们发现解决方法

    时,他们才发觉保密通信是精美的艺术。而麦考密克也以精确

    的类比进行了解释,读者无须拥有计算机科学知识就能理解。

    这些优点使这本书在科普读物领域做出了不可估量的贡献,我

    极力推荐这本书。

    克里斯·毕晓普(Chris Bishop)

    微软剑桥研究院资深科学家

    大不列颠皇家学院副院长

    爱丁堡大学计算机科学教授

    数在线交易都使用该技术存储及检索信息。

    发明了一种在数据库中组织信息的先进方法。目前,绝大多

    ● 1969年,IBM(国际商业机器公司)的一名研究人员

    望之后,我们仍期待出现一个真正的智能计算机程序。

    能领域的研究。在取得了许多重大成功,也经历了无数次失

    议。这次会议的目标很清晰,也很大胆,那就是开创人工智

    ● 1956年,一群学者在达特茅斯(Dartmouth)举行会

    干扰而遭受破坏。

    算机能以完美的精确度传输信息,即便大部分数据都因为被

    文,由此开创了信息理论研究领域。这位科学家的工作让计

    ● 1948年,一位供职于电话公司的科学家发表了一篇论

    大、设计得多好,仍旧有一些问题将是计算机不能解决的。

    继 续 证 明 了 , 不 管 未 来 建 造 的 计 算 机 运 行 多 快 、 功 能 多 强

    位英国天才开创了计算机科学研究领域。之后,这位天才还

    ● 20世纪30年代,在第一台数字计算机被发明以前,一

    进行介绍:

    计算机科学中的伟大思想是如何诞生的?以下遴选部分思想

    计算机日常运用的卓越思想

    前言● 1974年,英国政府秘密通信实验室的研究人员发明了

    一种让计算机实现安全通信的方法,即另一台计算机可以查

    看在计算机之间交换的所有信息。这些研究人员为政府保密

    所限——不过幸运的是,三名美国专家独立开发并拓展了这

    项重大发明,为互联网上所有的安全通信打下了基础。

    ● 1996年,斯坦福大学的两名博士生决定联手搭建一个

    互联网搜索引擎。几年后,他们创办了谷歌公司——互联网

    时代的第一个数字“巨头”。

    我们在享受21世纪技术惊人增长的同时,使用计算机设备

    ——不管是现有最强大的一组机器,还是最新、最时尚的手持设

    备——不可避免地要依赖计算机科学的基础思想,而这些思想都

    诞生于20世纪。想一想:你今天做过什么令人印象深刻的事情

    吗?好吧,这个问题的答案取决于你怎么看。也许是你搜索了包

    含数十亿份文档的资料库,从中选出两三份与你的需求最相关的

    文档?即便有能够影响所有电子设备的电磁干扰,你在存储或传

    输数百万条信息的过程中,也没犯一点儿错误?你是否成功地完

    成了一次在线交易,即便同时有成千上万名消费者在访问同一个

    服务器?你是否在能够被其他数十台计算机嗅探到的线路中传输

    了一些机密信息(比如信用卡卡号)?你是否运用过压缩的魔

    力,将数兆的照片压缩成更易于管理的大小,以便附在电子邮件

    中发送?你是否在手持设备上触发了人工智能,以自动纠正你在

    手持设备的小巧键盘上输入的内容?

    这些令人印象深刻的壮举都有赖于之前提到的伟大发明或发

    现。然而,绝大多数计算机用户每天都会多次运用这些天才的想

    法,却从没有意识到!本书旨在向大众解释这些观点——我们每天使用的计算机科学的伟大思想。在解释每一个观点时,我都假

    设读者不了解有关计算机科学的任何知识。

    算法:指尖“精灵”的构件

    到目前为止,我一直在谈计算机科学的伟大“思想”,但计

    算机科学家们会将许多重要思想形容为“算法”。那么思想和算

    法之间有什么区别?究竟什么是算法?这一问题最简单的答案

    是,算法是一张精确的处方,它按顺序详细列出了解决一个问题

    所需要的具体步骤。我们小时候在学校学到的一种算法就是很好

    的例子:将两个大数字相加的算法。如下例所示。这个算法涉及

    一连串的步骤,开始的步骤如下:“首先,将两个数的最末位数

    相加,写下结果的最末位数,将剩下的数放到左侧的下一栏;接

    着,将下一栏的数相加,再将除了结果末位数的数字和前一栏余

    下的数相加……”依此类推。

    图1 将两个数字相加的算法的前两步

    请注意算法步骤近乎机械化的感觉。事实上,这是算法的关

    键特点之一:每步都必须绝对精确,没有任何人类意图或推测掺

    杂其中。这样,每个完全机械化的步骤才能被编入计算机。算法的另一个重要特点是,不管输入什么,算法总能运行。我们在学

    校学到的相加算法就拥有这一特性:不管你想把哪两个数相加,运用算法最终都会得出正确答案。比如,用这一算法将两个长达

    1 000位的数相加,你肯定能得到答案,尽管这需要相当长的时

    间。

    对把算法定义为一张精确的机械化的处方的说法,你也许会

    略感好奇。这张处方究竟要多精确?要进行哪些基本操作?比

    如,在上面的相加算法中,简单地说一句“把两个数相加”是不

    是就行了?还是说我们要在加法表上列出所有位的数字?这些细

    节看起来也许有点儿乏味,甚至会显得有点儿学究气,但它们其

    实离真相不远了:这些问题的真正答案正处于计算机科学的核

    心,并且也和哲学、物理学、神经科学及遗传学有联系。有关算

    法究竟是什么的深层问题都归结于一个前提——众所周知的邱奇

    –图灵论题(Church-Turing thesis)。我们将在第九章重温这

    些问题,届时我们还将讨论计算的理论极限,以及邱奇–图灵论

    题的一些方面。同时,将算法比作一张非常精确的处方这一非正

    式观点,其效果会非常好。

    现在我们知道了什么是算法,但算法和计算机有什么联系

    呢?关键在于,计算机需要用非常精确的指令编程。因此,在能

    让计算机为我们解决某个特定问题之前,我们需要为那个问题开

    发一种算法。在数学和物理学等其他学科中,重要的结果通常是

    由一个方程式获得的。(著名的例子包括勾股定理a2+b2=c2或爱

    因斯坦的质量守恒定理E=mc2。)相反,计算机科学的伟大思想

    通常是来形容如何解决一个问题的——当然,是使用一种算法。因此,本书的主要目的是,解释让计算机成为你的个人天赋的东

    西——计算机每天使用的伟大算法。

    一种伟大的算法由什么构成?

    这会引出一个刁钻的问题:什么才是真正伟大的“算法”?

    潜在的候选算法清单相当长,但我用几条基本标准缩减了用于本

    书的候选算法清单。第一条也是最重要的一条标准是,伟大的算

    法要被普通计算机用户每天用到。第二条重要的标准是,伟大的

    算法应该能处理具体的现实问题,如压缩一个特定文件或通过一

    个噪链精确地传输文件。对已经了解部分计算机科学的读者而

    言,第XIII页文字框中的内容将解释前面两大标准的部分后果。

    第三个标准是,算法主要和计算机科学理论相关。这排除了

    主要和计算机硬件——如CPU(中央处理器)、监视器,以及网

    络——有关的技术。这条标准也减轻了对基础设施——如互联网

    ——设计的重视。为什么我要着重于计算机科学理论?部分原因

    是公众对计算机科学认知的不平衡:有一种广泛的观点认为,计

    算机科学基本上就是编程(如“软件”)和设备设计(如“硬

    件”)。事实上,最美妙的计算机科学思想中有许多是十分抽象

    的,并不属于以上任意一类。我希望通过强调这些理论思想,让

    更多人将计算机科学作为一门知识学科来理解。

    你也许已经注意到了,我列出的标准可能会遗漏一些伟大的

    算法,但我从一开始就避免了定义“伟大”这个极其麻烦的问

    题。针对这一问题,我依赖于自己的直觉。在本书说明的每种算

    法中,其核心都是一个让整件事情奏效的精巧把戏(trick)。对 我 而 言 , 当 这 个 把 戏 显 露 出 来 时 , 那 个 “ 啊 哈 时

    刻”(即“aha”moment,指用户体验产品时眼前一亮的那一

    刻)会让解释这些算法成为令人愉悦的经历,我希望你也能有此

    感受。我会用到“把戏”这个词很多次,需要指出的是,我并非

    指那些卑劣或骗人的把戏——孩子可能会用在弟弟或妹妹身上的

    那种把戏。相反,本书中的把戏类似于交易诀窍或魔术:为达成

    目标而采用的聪明技巧,否则目标很难达成或根本不可能达成。

    因此,根据直觉,我选出了自认为是计算机科学世界中最精

    巧、最神奇的把戏。在英国数学家高德菲·哈罗德·哈代

    (G.H.Hardy)的《一个数学家的辩白》(A Mathematician’s

    Apology)中,作者试图向公众解释数学家从事数学的原因

    ——“美是第一道测试:丑陋的数学在这个世界中无永存之

    地”。这道“美的测试”也适用于在计算机科学中蕴含的理论思

    想。因此,选取在本书中出现的算法的最后一条标准,就是哈代

    的——也许可以这么称呼——“美的测试”:我希望至少能成功

    地向读者展示部分美——我在每种算法中感受到的美。

    第一条标准——要被普通计算机用户每天用到——排除

    了主要由计算机专业人士使用的算法,如编译器和程序验证

    技术。第二条标准——解决某个特定问题的具体程序——排

    除了许多作为计算机科学本科课程核心内容的伟大算法,如

    排序算法(快速排序等)、图形算法(迪杰斯特拉最短路径

    算法等)、数据结构(哈希表等)。这些算法的伟大性毋庸

    置疑,而且很轻易地就满足了第一条标准,因为普通用户使

    用的绝大多数应用程序都会反复应用这些算法。但这些算法

    太通用了:它们能被用来解决众多问题。在本书中,我决定要专注于解决特定问题的算法,因为对普通计算机用户而

    言,这些算法能让他们拥有更清晰的动机。

    接下来我将谈谈选择展示的这些算法。搜索引擎的巨大影

    响,也许是算法技术影响所有计算机用户最明显的例子,我自然

    也将部分互联网搜索的核心算法收在了本书中。第一章描述了搜

    索引擎如何使用索引寻找与请求匹配的文件,而第二章则解释了

    网页排名(PageRank)算法——谷歌公司为保证匹配度最高的文

    件出现在搜索结果列表顶部的原始算法。

    即便我们不经常想这件事情,绝大多数人也能意识得到,为

    提供出人意料的强大搜索结果,搜索引擎会落实一些深邃的计算

    机科学思想。相反,其他一些伟大的算法也经常被用到,但计算

    机用户对此甚至都没有意识到。第三章描述的公钥加密(Public

    Key Cryptography)就是这样一种算法。用户每次访问一个安全

    网站(地址以https而非http开头),都会用到公钥加密的一个

    方面——众所周知的密钥交换(key exchange)——来展开一段

    安全对话。第三章就是在解释密钥交换过程的实现原理。

    第四章的主题是纠错码(Error Correcting Codes),这是

    我们经常使用但没有意识到的另一类算法。事实上,纠错码极有

    可能是有史以来唯一一种使用次数最频繁的伟大算法。纠错码可

    以让计算机识别并纠正在储存或传输数据时出现的错误,而不必

    依靠备份或再次传输。纠错码无处不在:它们被用于所有硬盘驱

    动器、众多网络传输、CD(数字光盘)和DVD(高密度数字视频

    光盘),甚至还存在于一些计算机的内存中。不过,纠错码的能

    后很有可能只占据电子邮件提供商5 GB空间的很小一部分。

    子邮件提供商提供给你的5GB(计算机存储单位)空间,经压缩

    节省带宽,而数据中心通常会压缩消费者的数据以降低成本。电

    高:我们根本没有意识到,我们的下载或上传也可以通过压缩以

    量,以便用电子邮件发出。不过在私底下,压缩使用的频率要更

    接进行压缩,也许是为了节省磁盘空间,也许是为了缩减照片容

    成我们“指尖精灵”的伟大思想。计算机用户的确会时不时地直

    第六章讨论了压缩算法。压缩算法组成了另一组使计算机变

    (Neural Network)。

    Classifier)、“决策树”(Decision Tree),以及神经网络 趣、最成功的图形识别技术:最近邻分类器(Nearest-neighbor 偏好,因为它是我的研究领域。因此,第五章描述了三种最有

    图形识别来决定向用户展示哪种广告。另外,我对图形识别也有

    (特别是智能手机)越来越趋向于语音操作。一些网站甚至使用

    需要自动纠错,平板设备必须识别手写输入,而且所有这些设备 年,图形识别的重要性急剧增大:配备小型屏幕键盘的移动设备

    个十年里,绝大多数日常计算并没有用到这些技术。但在2010

    ——如笔迹、讲话和人脸——的技术。事实上,在21世纪的第一

    计算机用户每天用到。图形识别属于计算机识别高度可变信息

    伟大的计算机科学思想榜单,但它违背了第一条标准:要被普通

    (Pattern Recognition Algorithm)。图形识别算法也能进入

    第 五 章 稍 微 有 点 儿 特 殊 , 它 介 绍 的 是 图 形 识 别 算 法 力太强了,以至于我们意识不到它们的存在。第七章讲到了数据库中运用的一些基础算法。这一章侧重为

    实现一致性——指一个数据库中的关系不互相冲突——而采用的

    聪明技巧。没有这些精巧的技术,我们的绝大部分在线生活[包

    括网络购物以及通过Facebook(“脸书”)之类的社交网站进行

    互动]就会消亡于众多计算机错误中。这一章解释了一致性真正

    的问题是什么,以及计算机科学家是如何解决这一问题的。前提

    是不牺牲我们所期望的在线系统拥有的高效性。

    在第八章,我们会了解理论计算机科学无可争议的瑰宝之

    一:数字签名。乍看之下,用数字形式“签署”一份电子文档似

    乎不可能。你也许会想,这种签名必须由数字信息组成,而任何

    想要伪造签名的人都可以毫不费力地拷贝这些信息。这一悖论的

    解决方案,就是计算机科学取得的最令人瞩目的成就之一。

    第九章采取了截然不同的视角:与其描述一种已经存在的伟

    大算法,我们不如去了解一种假如存在则必然会伟大的算法。不

    过我们会震惊地发现,这种特别伟大的算法不可能存在。这表明

    计算机解决问题的能力存在绝对极限,而我们将简单地从哲学和

    生物学角度探讨这一结果的应用。

    在结语部分,我们会总结伟大算法的一些共性,花些时间畅

    想未来会怎样。会有更多伟大算法出现吗?或者说,我们已经发

    现了所有伟大的算法?

    在此,不得不提前说一下本书的风格。任何科普作品都必须

    清楚地告知读者信息来源,但引用会破坏文本的流畅性,并让读

    者产生阅读学术著作的感觉。由于可读性和易读性是本书的首要

    目标,所以本书正文不会出现引用。不过,我清楚地记录了所有来源,并在本书末尾的“注释”板块中列出,还时不时地附上拓

    展评论。这个板块还列出了一些额外材料,以便感兴趣的读者能

    去寻找更多和计算机科学中伟大算法有关的信息。

    为什么我们要关注这些伟大的算法?

    希望对这些迷人思想的快速总结能让你渴望深入了解它们的

    运行方式。不过,也许你仍然在思考:本书的终极目标是什么?

    让我简短地介绍一下本书的真正目的。这本书绝不是一本问答式

    操作手册。在读完本书后,你不会成为计算机安全方面的专家,也不会成为人工智能或其他领域的专家。你也许能学到一些有用

    的技能,这倒是真的。比如:你会对如何检查“安全”网站凭证

    以及“已签名”软件包了解更多;你能在有损和无损压缩之间针

    对不同任务做出明智选择;通过理解搜索引擎索引和排名技术的

    某些方面,你能更高效地使用搜索引擎。

    然而,这些相对于本书真正的目的不过是微小的红利。在读

    完本书后,你不会成为一名更加熟练的计算机用户,但你会更加

    珍视每天在所有计算设备上不停使用的思想的美。

    为什么这是件好事?我用类比的方式来说明。我肯定不是一

    位天文学专家——事实上,我在这个领域里相当无知,我想知道

    更多。但每当我注视夜空时,我知道的少量天文学知识增强了我

    此刻的享受。有时,我对所见事物的理解,让我产生了一种满足

    和惊奇的感觉。希望在读完本书后,你在使用计算机时也能经常

    获得同样的满足和惊奇之感,这也是我殷切的希望。你将真正珍视我们时代最常见、最神秘的黑盒子:你的个人电脑,你指尖

    的“精灵”。第一章

    搜索引擎索引

    ——在世界上最大的草垛中寻针哈克,在咱们俩站着的地方的下面,你拿一根钓鱼竿就

    可以触到我钻出来的那个洞。看看你能不能找到它。

    ——马克·吐温,《汤姆·索亚历险记》(Tom Sawyer)

    搜索引擎对我们的生活产生了深远影响。绝大多数人每天都

    进行多次搜索查询,但我们极少会停下来思考这个令人惊叹的工

    具是如何奏效的。搜索引擎提供的海量信息以及搜索结果的速度

    与质量变得如此平常,如果我们搜索的问题没有在几秒内得到回

    答,我们就会感到困惑。我们倾向于忘记,每个成功的搜索引擎

    都是从世界上最大的草垛——万维网(www)——中寻针的。

    事实上,搜索引擎提供的超级服务,不仅仅是针对搜索抛出

    花哨技术产生的一大堆结果。的确,每家大型搜索引擎公司都运

    营着一个由无数数据中心组成的国际网络,其中包括数以千计的

    计算机服务器和先进的网络设备。但若没有聪明的算法来组织和

    检索我们要寻找的信息,所有这些硬件都会变得毫无用处。因

    此,在这一章和下一章,我们将探究这样一些算法瑰宝——每次

    在进行网络搜索时,我们都会用到这些算法。我们很快就会了解

    到,搜索引擎的两大主要任务就是匹配(matching)和排名

    (ranking)。这一章将讲述一种聪明的匹配技术:元词把戏

    (Metaword Trick)。在下一章,我们将转而讨论排名任务,审

    视谷歌公司著名的网页排名算法。匹配和排名

    当你发起一次网络搜索查询时会发生什么?以这样一种高屋

    建瓴的视角开始会很有帮助。我已经说过,搜索有两个主要阶

    段:匹配和排名。在实际运行中,搜索引擎将匹配和排名组合成

    一个流程以实现一致性。但这两个阶段在概念上是独立的,因此

    我们会假设在排名开始前,匹配已经完成了。下图就给出了一个

    例子,图中查询的是“London bus timetable”(伦敦公共汽车

    时刻表),而匹配阶段则回答了“哪个网页与我的查询匹配”这

    个 问 题 —— 在 这 个 例 子 中 就 是 所 有 提 到 “London bus

    timetable”的网页。

    图2 网络搜索的两个阶段:匹配和排名。在第一阶段(匹配)后可能会出现数千

    或数百万个匹配结果,这些结果必须按照相关度在第二阶段(排名)进行排序

    现实搜索引擎中的许多查询都有数百、数千,乃至数百万

    个“命中”,而搜索引擎用户通常只喜欢查看几个结果,5个或

    最多10个。因此,搜索引擎必须从大量“命中”里挑出最好的几

    个。一个好的搜索引擎不仅会挑出最好的几个“命中”,而且会以最有用的顺序显示它们——将最匹配的页面排在第一,然后是

    匹配度排名第二的页面,其后依此类推。

    以正确顺序挑选出最好的几个“命中”,这被称为“排

    名”。排名是第二个关键阶段,紧随最开始的匹配阶段。在搜索

    行业的残酷世界中,搜索引擎的生死由其排名系统的质量决定。

    2002年,美国前三大搜索引擎的市场份额基本相当,谷歌、雅虎

    和MSN(微软公司旗下的门户网站)在美国的市场份额都在30%以

    下。MSN随后被重新包装成实时搜索引擎,之后又被命名为必应

    (Bing)。之后几年,谷歌的市场份额迅速扩大,同时将雅虎和

    MSN的市场份额分别打压到了20%以下。人们普遍认为,谷歌迅速

    上升为搜索行业冠军是得益于其排名算法。因此,毫不夸张地

    说,搜索引擎的生死由其排名系统的质量决定。不过,正如我已

    经提到的,我们将在下一章探讨排名算法。至于现在,让我们专

    注于匹配阶段吧。

    AltaVista[1]:互联网级别的第一种匹配算法

    搜索引擎匹配算法的故事从哪里开始?一个很显然却错误的

    回答是从谷歌——21世纪初期最伟大的技术成功故事——开始。

    事实上,谷歌最初只是斯坦福大学两位学生的博士学位项目,这

    个故事不仅温暖人心,而且令人印象深刻。拉里·佩奇(Larry

    Page)和谢尔盖·布林(Sergey Brin)在1998年组装了一堆计

    算机硬件来运行一种新的搜索引擎。不到10年,他们的公司就成

    了互联网崛起时代最伟大的“数字巨人”。不过,互联网搜索的想法已经存在很多年了。最早的商业应

    用是Infoseek和Lycos(两者都于1994年被推出),以及于1995

    年推出搜索引擎的AltaVista。20世纪90年代中期,AltaVista是

    搜索引擎的王者。当时我还是一名计算机科学专业的研究生,我

    清楚地记得自己惊叹于AltaVista搜索结果的成熟度。有史以来

    第一次,有一个搜索引擎能完全索引互联网上每个页面的全部文

    本。更可贵的是,眨眼间它就能返回结果。要继续理解这个令人

    回味的技术突破,我们就要从接触一个古老的(毫不夸张)概念

    ——索引——开始。

    古老的索引

    索引的概念是所有搜索引擎背后最基础的思想。但索引并非

    由搜索引擎发明:事实上,索引的思想几乎和书写本身一样古

    老。比如,人类学家发现了一座具有五千年历史的古巴比伦神庙

    图书馆,里面按学科对楔形文字泥版进行了分类。因此,索引可

    以称得上是计算机科学中最古老的有用思想。

    如今,“索引”这个词通常指参考书的最后一个板块。你可

    能想要查看的所有概念都以固定顺序(通常是按字母排序)被列

    出,每个概念下都列出了这个概念出现的位置(通常是页码)。

    因此,一本和动物有关的书也许会有一个像“cheetah(猎豹)

    124,156”的索引项。这个索引项意味着“cheetah”这个词在

    第124页和第156页出现过。图3 一个假想的万维网,由编号为1、2和3的3个页面组成

    互联网搜索引擎的索引和一本书的索引有着相同的工作原

    理。“书页”现在成了万维网上的网页,而搜索引擎则给互联网

    上的每个网页分配了一个不同的页码。(是的,互联网上虽然有

    很多网页——最新的数据显示有成百上千亿个——但计算机很擅

    长处理大量数字。)下一页的图给出了一个会让整个过程更具体

    的例子。想象一下万维网只由上面显示的3个短网页组成,它们

    分别匹配页码1、2和3。

    计算机可以为这三个网页创建一个索引:首先要为出现在任

    一页面上的所有单词创建一份列表,然后按字母表的顺序整理这

    张列表。我们可以将结果称为单词表(word list)——在这个

    例子中是“a、cat、dog、mat、on、sat、stood、the、while”。然后计算机会一个单词一个单词地搜遍所有页面。计

    算机会标注每个单词所在的页码,然后再标注单词表中下一个单

    词的位置。最终结果显示在下图中。比如,你可以立即看到单

    词“cat”出现在第1页和第3页,却不在第2页;而单

    词“while”只出现在第3页。

    通过这种简单的方法,搜索引擎就能答复许多简单的查询。

    比如,假设你输入查询词“cat”,搜索引擎能很快跳转到单词

    表中的“cat”项。(因为字母表是按字母排序的,计算机能很

    快找到任何一项,就像我们可以很快找到词典中的一个单词一样。)一旦计算机找到“cat”项,搜索引擎就能给出该项的页

    面列表——在这个例子中就是第1页和第3页。现代搜索引擎对结

    果的组织很合理,只摘取了返回页面的少许片段,不过,我们基

    本上会忽略这样的细节,而将精力集中在搜索引擎如何知道页

    面“符合”用户输入的查询上。

    图4 一个用页码表示的简单索引

    再 举 一 个 非 常 简 单 的 例 子 , 让 我 们 来 检 查 一 下 查

    询“dog”的步骤。在这个例子中,搜索引擎很快会找

    到“dog”项,并返回页码2和3。如果查询多个单词,如“cat

    dog”呢?这表示你正在寻找同时包含单词“cat”和“dog”的

    页面。通过已有的索引,搜索引擎也能很容易地查到结果。搜索

    引擎首先会单独查找这两个单词,找出它们分别在哪些页面中。

    结果是“cat”在第1页和第3页,“dog”在第2页和第3页。之

    后,计算机能快速扫描这两份“命中”列表,寻找同时出现在两

    份列表中的页码。在这个例子中,第1页和第2页被排除了,而第

    3页同时出现在两份列表中,因此最终答案就是第3页上的一次单

    独“命中”。与之极其相似的一个策略也适用于超过两个单词的查询。比如,查询“cat the sat”会得到第1页和第3页为“命

    中”的结果,因为它们是“cat”(1,3)、“the”(1,2,3)和“sat”(1,3)这份列表的通用元素。

    就目前来看,搭建一个搜索引擎听起来相当容易。最简单的

    索引技术似乎运行得很好,即便查询多词也是如此。不幸的是,这种简单方法完全不能满足现代搜索引擎的需要。出现这种情况

    的原因有几个,不过现在我们只会关注其中之一:如何做短语查

    询。短语查询是指对于一个确切短语的查询,而非凑巧的一些单

    词出现在页面中的某些地方。比如,“cat sat”查询和cat sat

    查询的意义截然不同[2]。cat sat查询的是在任何位置包

    含“cat”和“sat”两个单词的页面,不考虑顺序;而“cat

    sat”查询的是包含单词“cat”之后紧跟单词“sat”的页面。

    在上面那个由三个网页组成的简单例子中,cat sat查询结

    果“命中”第1页和第3页,但“cat sat”查询只得到一次“命

    中”的结果,就在第1页。

    一个搜索引擎如何才能有效地进行一次短语查询呢?继续

    说“cat sat”这个例子。第一步和平常的多词查询cat sat一

    样,从单词表中获取每个单词出现的网页列表,在这个例子中就

    是出现在第1页和第3页的“cat”;“sat”也一样,出现在第1

    页和第3页。不过搜索引擎到这里就卡住了。搜索引擎很确切地

    知道两个单词同时出现在第1页和第3页上,但没有办法来分辨这

    些单词是否以正确的顺序紧挨着彼此出现。你也许会想,搜索引

    擎可以返回查看原网页,看这个短语是否存在。这的确是个可能

    的解决方案,但效率非常低。这需要遍历每个可能包含这个短语

    的网页的全部内容,而且可能有海量这样的网页。记住,我们在这里打交道的是一个只由3个页面组成的极小的例子,真正的搜

    索引擎必须从数百亿个网页中找出正确的结果。

    词位置把戏

    这一问题的解决方案是让现代搜索引擎运行良好的首个真正

    精巧的思想:索引不仅应该存储页码,还要存储信息在页面内的

    位置。这些位置并不神秘:它们只是代表了一个词在页面中的位

    置。第3个词的位置是3,第29个词的位置是29,依此类推。例子

    中3个页面组成的数据集如下页图所示,我们还加上了词位置。

    图下面的是索引——由存储页码和词的位置得出的结果组成。我

    们称这种创建索引的方法为“词位置把戏”(Word-location

    Trick)。举几个例子,以确保大家理解了词位置把戏。索引的

    第一行是“a 3–5”。这意味着词“a”只在数据库里集中出现

    过一次,是第3页的第5个单词。索引中最长的一行是“the 1–1

    1–5 2–1 2–5 3–1”。这一行可以让你知道,这组数据集中

    了出现单词“the”的所有具体位置。它在第1页出现过2次(位

    置1和5),在第2页出现过2次(位置1和5),在第3页出现过1次

    (位置1)。

    你还记得介绍页内词位置的目的吗?是为了解决如何有效地

    进行短语查询这个问题。让我们来看看如何用这个新索引做一次

    短语查询。还是和前面一样,查询短语“cat sat”。第一步和

    使用旧索引时一样:从索引中提取单个词的位置,“cat”的位

    置是1–2、3–2,“sat”的位置是1–3、3–7。到这里还好,因为我们知道短语查询“cat sat”唯一可能的“命中”就是在第1页和第3页。但与之前一样,我们还不确定相同的短语是否出

    现在了这些页面中——有可能这两个单词的确出现了,但并不是

    以正确的顺序彼此相邻。幸运的是,从位置信息中确认这一点很

    容易。首先从第1页开始。根据索引信息,我们知道“cat”出现

    在第1页的位置2(这就是1–2的含义)。我们还知道“sat”出

    现在第1页的位置3(这是1–3的含义)。如果“cat”在位置

    2 , “sat” 在 位 置 3 , 我 们 就 知 道 “sat” 紧 挨 着 出 现

    在“cat”之后(因为2之后立即就是3),因此我们寻找的整个

    短语“cat sat”必定出现在第1页,并从位置2开始。

    图5 上图:在3个网页里加上了页内词位置;下图:同时包含页码和页内词位置

    的新索引

    我知道自己在这点上谈得很多,但事无巨细、从头至尾地研

    究这个例子,是为了让读者真正地理解为了获得答案,我们究竟

    使用了哪些信息。注意,我们已经为短语“cat sat”找到了一

    次“命中”,仅是通过查看索引信息(“cat”的位置1–2、3–2,“sat”的位置1–3、3–7)而非原始网页。这很关键,因为

    我们只需查看索引中的两个项,而非遍历可能包含“命中”的所

    有页面——而在真正进行短语查询的搜索引擎中,可能有数百万

    个这样的页面。总之,通过在索引中加入页内词位置,我们只需

    查看索引中的几行,就能找到一次短语查询“命中”,而非遍历

    海量页面。这个简单的词位置把戏是让搜索引擎奏效的关键之

    一。

    事实上,我还没讲完“cat sat”这个例子。我们完成了对

    第1页信息的处理,但还没处理第3页的信息。对第3页的推理和

    第1页的处理方式很相似:“cat”出现在第3页的位置

    2,“sat”出现在位置7,因此它们不可能相邻——因为紧跟2之

    后出现的不是7。这样我们就知道,第3页并不是短语查询“cat

    sat”的“命中”,尽管它是多词查询cat sat的“命中”。

    顺便说一下,词位置把戏不只对短语查询重要。举个例子,思考一下寻找相邻单词的问题。在一些搜索引擎中,用户可以在

    查询中使用“NEAR”(邻近)关键词做到这一点。事实上,AltaVista搜索引擎在早期就提供了这一功能,在本书写作时仍

    在提供。假设在一些特别的搜索引擎中,查询cat NEAR dog会找

    到“dog”前后五个位置之内出现“cat”的页面。我们如何才能

    在数据库中有效地执行这种查询?使用词位置会使查询变得很容

    易。“cat”的索引项是1–2、3–2,而“dog”的索引项是2–

    2、3–6。我们可以立刻看出,第3页是唯一可能的“命中”。而

    在第3页,“cat”出现在位置2,“dog”出现在位置6。因此这

    两个词之间的距离是4。因此,“cat”的确出现在“dog”前后

    五个位置之内,而第3页则是查询cat NEAR dog的“命中”。和前面一样,请注意这次查询的执行是多么高效:无须遍历任何网

    页的实际内容——相反,只参考了索引中的两个项。

    不过,在实际中,NEAR查询对搜索引擎用户并不非常重要。

    几乎没人使用NEAR查询,绝大多数主要搜索引擎甚至不支持它

    们。尽管如此,能执行NEAR查询的能力实际上对现实中的搜索引

    擎至关重要。这是因为搜索引擎不断地在后台执行NEAR查询。要

    想理解其中的原因,我们先要研究现代搜索引擎面临的主要问题

    之一:排名。

    排名和邻度

    到目前为止,我们一直专注于匹配阶段:为一个给出的查询

    高效地找出所有“命中”的问题。不过正如之前强调的,第二个

    阶段“排名”对一个高质量的搜索引擎是必不可少的,它是挑选

    出前几个“命中”并展示给用户的阶段。

    让我们更细致地来检验“排名”的概念。一个网页的“排

    名”究竟取决于什么?真正的问题不是“这个网页和查询匹配

    吗”,而是“这个网页和查询相关吗”。计算机科学家们使

    用“相关度”(relevance)这个术语来形容一个结果网页和某

    个特定查询有多么相配或这个网页多么有用。

    举个具体的例子,假设你对导致疟疾的原因感兴趣,并在一

    个搜索引擎中输入查询malaria cause(导致疟疾)。简化考

    虑,假设搜索引擎对这一查询只有两个“命中”——下图显示的

    两个网页。现在来看看这两个网页。作为人类,你很快就知道第1页和疟疾起因有关,而第2页似乎是对刚刚发生的一些军事行动

    的描述,只不过恰巧使用了“cause”和“malaria”这两个词。

    因此,和第2页相比,第1页无疑和查询malaria cause更相关。

    可计算机不是人,让计算机理解这两页的主题也很难,似乎不可

    能让搜索引擎正确地对这两个“命中”进行排名。

    图6 上两图:两个提及疟疾的样本网页;下图:从上方两个网页中创建的索引的

    一部分

    不过,事实上,有一种很简单的方法让这个例子中的排名正

    确。查询词彼此相邻的网页比那些查询词相距很远的网页相关度

    更高。在疟疾这个例子中,“malaria”和“cause”在第1页中

    仅相距1个词,而在第2页中则相距17个词。(记住,搜索引擎只

    通过查看索引项就能高效地发现这一点,无须返回查看网页。)

    因此,尽管计算机并不真正地“理解”查询的主题,它也能猜测网页1比网页2更具相关性,因为网页1查询词之间的距离要比在

    网页2中更近。

    总而言之,尽管人们不经常使用NEAR查询,搜索引擎也在不

    断地使用和邻度有关的信息,以提高搜索排名。而它们能高效地

    做到这点的原因则是,它们使用了词位置把戏。

    我们已经了解到,早在距今5 000年以前,古巴比伦人就开

    始使用索引。而词定位把戏也不是由搜索引擎发明的:这是互联

    网出现以前,在另一种信息检索中用到的著名技术。不过,在下

    一部分,我们将了解一个看起来的确是由搜索引擎设计者发明的

    新把戏:元词把戏。对这一把戏和众多相关思想的精巧运用,使

    AltaVista搜索引擎在20世纪90年代晚期迅速成为搜索行业

    的“领头羊”。

    元词把戏

    到目前为止,我们一直都在使用极其简单的网页示例。然

    而,绝大多数网页拥有众多结构,包括标题、标头、链接和图

    片,可我们还一直认为网页只是普通的词表。接下来,我们将探

    索搜索引擎如何处理网页中的结构。不过,为了尽可能地保持简

    单,我们只会引入一层结构:网页的顶部会有一个标题,之后是

    页面的正文。下图显示了我们熟悉的三页示例,并附加了一些标

    题。图7 一个网页范例集,每个网页都有一个标题和一段正文

    实际上,要像搜索引擎一样分析网页结构,我们就需要了解

    更多编写网页的知识。网页是由一种特殊语言编写的,以便网络

    浏览器能用很好的格式展示它们。编写网页最常用的语言被称为

    HTML,不过HTML的细节对本次讨论来说不重要。标头、标题、链

    接、图片等格式化结构是用被称为元词的特殊单词编写的。比

    如,网页标题开始使用的元词也许是,而结束这个

    标题的元词可能是。类似的,网页正文可能是以

    开始,以结束。不要纠结于“<”“>”这

    些符号。它们出现在绝大多数计算机键盘上,人们通常只知道这

    些符号的数学意义是“小于”和“大于”。不过在这里,这些符

    号和数学没有任何关系,只是方便将这些元词和网页中的正常单

    词区分开来。

    请看图8。这张图展示的内容和图7一样,但这次显示的是实

    际编写网页的样子,而非在网络浏览器中显示的样子。绝大多数

    网络浏览器都能让用户检验网页的原始内容,这需要选择名

    为“查看网页源代码”的菜单选项——我建议你下次有机会试验

    一下。在这里使用的元词,如,是帮

    助你理解虚构的、易于辨认的示例。在真实的HTML中,元词被称

    作标签(tag)。HTML中开启和结束标题的标签是和<title>,你可以在使用“查看网页源代码”的菜单选项后搜索<br/><br/>     这些标签。在创建一份索引时,囊括所有元词是件很简单的事,你只要<br/><br/>     像存储正常单词一样存储元词位置就行。下页的图显示了从带有<br/><br/>     元词的3个网页中创建的索引。看一下这张图,确保自己理解了<br/><br/>     其中所有的奥秘。比如,“mat”的项是1–11、2–11,这表<br/><br/>     示“mat”是第1页的第11个词,也是第2页的第11个词。元词位<br/><br/>     置的解读也一样,“<titleEnd>”的项是1–4、2–4和3–4,也<br/><br/>     就是说“<titleEnd>”是第1页、第2页和第3页的第4个词。<br/><br/>     图8 和图7一样的网页集,但展示的是用元词编写的情况,而非在网络浏览器中<br/><br/>     显示的样子<br/><br/>     我们称这种和索引普通单词一样索引元词的简单把戏为“元<br/><br/>     词把戏”。这个把戏也许看起来简单得可笑,但元词把戏在让搜<br/><br/>     索引擎执行精确搜索和高质量排名上扮演了至关重要的角色。举<br/><br/>     个简单例子证明。假设在某个时候,有个搜索引擎支持使用IN关<br/><br/>     键词的特殊查询,因此像boat IN TITLE这样的查询只会得到在<br/><br/>     网页标题中包含单词“boat”(船)的网页的结果,而查询<br/><br/>     giraffe ( 长 颈 鹿 ) IN BODY 则 会 找 到 在 正 文 中 包<br/><br/>     含“giraffe”的网页。请注意,绝大多数搜索引擎并不完全按<br/><br/>     照这种方法提供IN查询,但一些搜索引擎可以通过让你点击“高<br/><br/>     级搜索”选项,详细说明查询词必须出现在标题或一份文件的特<br/><br/>     定位置来实现同样的效果。我们假定IN关键词存在,以便更容易<br/><br/>     解释。事实上,在写作本书时,谷歌已经可以让用户通过使用关键 词 intitle 进 行 标 题 搜 索 了 : 因 此 , 在 谷 歌 中 查 询<br/><br/>     intitle:boat,将找到标题中带有“boat”的网页。自己试试<br/><br/>     吧!<br/><br/>     让我们来看看,在下面图9和图10由三个网页组成的示例<br/><br/>     里,搜索引擎如何有效地执行查询dog IN TITLE。首先,搜索引<br/><br/>     擎提取“dog”的索引项,也就是2–3、2–7和3–11。然后(这<br/><br/>     可能有点儿出人意料,但请忍耐片刻)搜索引擎会同时提取<br/><br/>     <titleStart>和<titleEnd>的索引项。<br/><br/>     <titleStart>的索引项是1–1、2–1和3–1,<titleEnd>的<br/><br/>     索引项是1–4、2–4和3–4。这些提取信息全部显示在下图中,你可以忽略那些圈和框。<br/><br/>     图9 图8中的网页(包括元词)的索引图10 搜索引擎如何执行搜索dog IN TITLE<br/><br/>     之后,搜索引擎开始扫描“dog”的索引项,检查其“命<br/><br/>     中”,看是否有哪个“命中”出现在标题内。“dog”的第一<br/><br/>     个“命中”是圈起来的项2–3,代表其是第2页的第3个词。通过<br/><br/>     一并扫描<titleStart>的项,搜索引擎就能知道第2页的标题从<br/><br/>     哪儿开始——索引项的第一个数字要以“2–”开始,也就是被<br/><br/>     圈的项2–1,即第2页的标题从第1个单词处开始。同样地,搜索<br/><br/>     引擎能知道第2页的标题在哪儿结束。搜索引擎只要扫描索引项<br/><br/>     中的<titleEnd>,寻找以“2–”开始的索引项数字即可,在这<br/><br/>     个例子中就是停止在被圈的项2–4处,表明第2页的标题在第4个<br/><br/>     词处结束。<br/><br/>     我们目前已知的所有东西都被图中圈住的项总结了。它们告<br/><br/>     诉我们第2页的标题从第1个词开始,到第4个词结束,而“dog”这个词是第3个词。最后一步很简单:因为3大于1、小<br/><br/>     于4,所以我们能肯定“dog”的这次“命中”确实出现在一个标<br/><br/>     题中,因此第2页应该是查询dog IN TITLE的“命中”。<br/><br/>     现在搜索引擎可以转而寻找“dog”的第二个“命中”,也<br/><br/>     就是2–7(第2页的第7个词),但因为我们已经知道第2页是“命中”,因此可以忽略2–7这个项,而转向下一个“命<br/><br/>     中”3–11(由一个框标记)。这表示“dog”是第3页的第11个<br/><br/>     词。于是我们开始跳过被圈住的<titleStart>和<titleEnd>项,寻找以“3–”开始的项。有一点需要重点注意,我们不必回到<br/><br/>     每行的开始,而是可以从之前扫描“命中”的地方重新开始。在<br/><br/>     这个简单的例子中,以“3–”开始的项恰好彼此相邻——<br/><br/>     <titleStart>是3–1,<titleEnd>是3–4。为便于参考,我们将<br/><br/>     这两个数字用框围了起来。接下来,我们又面临判定“dog”在3<br/><br/>     –11的“命中”是否位于标题内的问题。框内信息告诉我们,它<br/><br/>     们都是在第3页,“dog”是第11个词,而标题从第1个词开始,到第4个词结束。因为11大于4,所以“dog”的这次“命中”出<br/><br/>     现在标题之后,也就是不在标题内。网页3并不是查询dog IN<br/><br/>     TITLE的“命中”。<br/><br/>     元词把戏能让搜索引擎以极其高效的方式回应有关一个文件<br/><br/>     结构的查询。上面的例子只是搜索页面标题内的词,但类似的技<br/><br/>     术能让用户搜索超链接、图片描述和网页其他有用部分内的词。<br/><br/>     而且所有这类查询都可以像上面的例子一样得到高效回应。正如<br/><br/>     我们之前讨论过的查询,搜索引擎无须返回查看原始网页:搜索<br/><br/>     引擎只需查阅小部分索引项,就能回应查询。同样重要的是,搜<br/><br/>     索引擎只需遍历每个索引项一次。还记得我们在完成处理第2页<br/><br/>     的首个“命中”后,转向第3页的可能“命中”时发生了什么<br/><br/>     吗?搜索引擎并没有返回索引项<titleStart>和<titleEnd>的开<br/><br/>     端,而是从之前离开的地方继续进行扫描。这也是让IN查询高效<br/><br/>     的关键因素。标题查询和其他取决于网页结构的“结构查询”类似于之前<br/><br/>     讨论的NEAR查询,虽然人们极少执行结构查询,但搜索引擎无时<br/><br/>     无刻不在内部使用它们。我们之前提过原因:搜索引擎的生死由<br/><br/>     其排名的质量决定,而通过利用网页结构,排名质量能够得到大<br/><br/>     幅提升。比如,标题中有“dog”的网页包含与狗有关信息的可<br/><br/>     能性,要比在网页正文中提及“dog”的网页大得多。因此,当<br/><br/>     一名用户输入简单的查询dog时,搜索引擎能在内部执行一个dog<br/><br/>     IN TITLE查询(即便用户并未详细地要求这一点),以寻找最有<br/><br/>     可能与狗有关的网页,而非只是恰好提到狗的网页。<br/><br/>     索引和匹配把戏并非全部内容<br/><br/>     搭建一个搜索引擎并不是一件容易的事情。最终成品就像一<br/><br/>     台巨大的复杂机器,它带有许多不同的轮子、发动机和杠杆。这<br/><br/>     些装置都必须安装正确,系统才能有用。因此,单靠在本章中出<br/><br/>     现的两个把戏并不能解决创建一个高效搜索引擎索引的问题,意<br/><br/>     识到这一点很重要。不过,词位置把戏和元词把戏无疑展现了真<br/><br/>     正的搜索引擎构建和使用索引的风格。<br/><br/>     元词把戏的确帮助过AltaVista——其他搜索引擎则失败了<br/><br/>     ——成功地在整个互联网中寻找有效匹配。我们之所以知道这一<br/><br/>     点,是因为AltaVista在1999年递交的美国专利文件《索引的限<br/><br/>     制搜索》(“Constrained searching of an index”)中描述<br/><br/>     了元词把戏。不过,AltaVista超级精巧的匹配算法并不足以让<br/><br/>     其从搜索行业波涛汹涌的早期脱颖而出。正如我们已经知道的,有效匹配只是高效搜索引擎的一大挑战,另一大挑战是对匹配网页进行排名。正如我们将在下一章中看到的,一种新排名算法的<br/><br/>     出现足以让AltaVista相形见绌,并让谷歌一跃升至网络搜索世<br/><br/>     界的最前沿。<br/><br/>     [1] AltaVista是全球知名网络搜索引擎公司,2003年被雅虎收购。雅虎于2013<br/><br/>     年7月8日已关闭AltaVista。——编者注<br/><br/>     [2] 注意英文单词的双引号。——译者注第二章<br/><br/>     PageRank<br/><br/>     ——让谷歌腾飞的技术《星际迷航》(Star Trek)中的计算机并不特别让人<br/><br/>     感兴趣。他们向计算机提问题,计算机还要想一会儿才能回<br/><br/>     答。我觉得我们能做得更好。<br/><br/>     ——拉里·佩奇<br/><br/>     从建筑学的角度来说,车库是简陋的地方。但在硅谷,车库<br/><br/>     有一种特殊的创业含义:许多伟大的硅谷技术公司在此诞生或至<br/><br/>     少从车库中“孵化”而来。这一趋势并非从20世纪90年代的互联<br/><br/>     网泡沫(指1995年至2000年围绕互联网公司形成的投机性投资泡<br/><br/>     沫)开始。在互联网泡沫出现的50多年前的1939年,当世界经济<br/><br/>     仍未从大萧条的影响中走出来时,惠普(Hewlett-Packard)就<br/><br/>     在加利福尼亚州帕罗奥图市(Palo Alto)戴夫·休利特(Dave<br/><br/>     Hewlett)的车库中逐渐成形了。几十年之后,史蒂夫·乔布斯<br/><br/>     (Steve Jobs)和史蒂夫·沃兹尼亚克(Steve Wozniak)于<br/><br/>     1976年在加利福尼亚州洛斯拉图斯市乔布斯的车库中创业,之后<br/><br/>     创建了今天堪称传奇的苹果计算机公司。(尽管传说苹果公司创<br/><br/>     建于车库,但乔布斯和沃兹尼亚克一开始其实是从一间卧室开始<br/><br/>     的。空间很快就不够用了,于是他们转移到了车库。)不过,和<br/><br/>     惠普与苹果的成功故事相比,一个名为谷歌的搜索引擎的创建过<br/><br/>     程更令人惊叹。谷歌从加利福尼亚州门洛帕克市的一间车库开<br/><br/>     始,并于1998年9月注册成立公司。<br/><br/>     那时,谷歌事实上已经运营自己的搜索引擎一年多了——最<br/><br/>     开始是在斯坦福大学的服务器上,谷歌的两位联合创始人都是斯<br/><br/>     坦福博士生。直到斯坦福大学再也不能承受这一日益受欢迎的服<br/><br/>     中”。<br/><br/>     并持续为搜索查询提供最相关的结果,也就是排名最靠前的“命<br/><br/>     章,我们将探索这一算法如何以及为什么能在“草垛中寻针”,是21世纪出现的第一个算法瑰宝的描述:PageRank算法。在本<br/><br/>     谷歌系统的完整描述。但藏在这一系统技术细节中的,是对也许<br/><br/>     论文的内容不只是描述PageRank。事实上,这是对1998年存在的<br/><br/>     Engine)中发表了这一算法。正如论文标题所暗示的那样,这篇<br/><br/>     Anatomy of a Large-Scale Hypertextual Web Search 的一篇学术会议论文《解析大规模超文本网络搜索引擎》(The<br/><br/>     又是其主要发明者拉里·佩奇的排名算法。佩奇和布林在1998年<br/><br/>     “PageRank”是个双关词:它既是一种对网页排名的算法,进行排名的创新算法:一个被称为PageRank的著名算法。<br/><br/>     之一——尤其是在网络搜索早期——就是谷歌用来对其搜索结果<br/><br/>     Lycos和AltaVista呢?这一问题的答案可不简单。但重要的因素<br/><br/>     怎么能弥补4年的巨大差距,在搜索质量上超越已经很受欢迎的<br/><br/>     第一个商业搜索引擎于4年前的1994年发布。还在车库里的谷歌<br/><br/>     得出相关度极高的结果”而获奖。你也许还记得上一章提到过,当年的评论中,谷歌的精英管理层因为谷歌“以超乎寻常的技巧<br/><br/>     这也是我们的故事真正开始的地方:在《个人计算机杂志》<br/><br/>     Magazine)就宣布谷歌是1998年美国排名前一百的网站之一。<br/><br/>     他 们 正 式 成 立 公 司 3 个 月 后 , 美 国 《 个 人 计 算 机 杂 志 》 ( PC 如今著名的门洛帕克车库。他们肯定做了一些正确的事,因为在<br/><br/>     务所需要的带宽,拉里·佩奇和谢尔盖·布林才把公司转移到了超链接把戏<br/><br/>     你很有可能已经知道了超链接是什么:超链接是网页上的一<br/><br/>     个短语,当你点击它时,你将被带到另一个网页。绝大多数网络<br/><br/>     浏览器用蓝色底线显示超链接,以便其能被轻易识别。<br/><br/>     令人意外的是,超链接也是老想法。1945年——大约是开始<br/><br/>     研发电子计算机的同一时期——美国工程师范内瓦·布什<br/><br/>     (Vannevar Bush)发表了一篇极具前瞻性的论文《诚若所思》<br/><br/>     (As We May Think)。在这篇涉猎广泛的论文中,布什描述了<br/><br/>     大量可能实现的新技术,包括一台被称作麦麦克斯(memex)的<br/><br/>     机器。麦麦克斯可以存储文件并自动进行索引,但其功能远不止<br/><br/>     这些。麦麦克斯允许“关联索引……任何被选中的东西都能立即<br/><br/>     自动选择另一个东西”,换句话说,那是一种早期的超链接。<br/><br/>     超链接自1945年起就已出现。它们是搜索引擎用来进行排名<br/><br/>     最重要的工具之一,而且是谷歌PageRank技术的基础。接下来,我们将开始以最大的热情探索PageRank技术。<br/><br/>     理解PageRank的第一步是一个名为超链接把戏(The<br/><br/>     Hyperlink Trick)的简单想法。用一个例子就能非常容易地解<br/><br/>     释这个把戏。假设你对学习如何制作炒蛋感兴趣,并且用网络搜<br/><br/>     索了这一主题。如今,任何一次真正搜索炒蛋的网络搜索都会出<br/><br/>     现数百万个“命中”,但为了方便起见,让我们想象只有两个网<br/><br/>     页出现:其中一个是“欧尼的炒蛋菜谱”,而另一个则是“伯特<br/><br/>     的炒蛋菜谱”。这两个网页都出现在下图中,与之一道的是拥有<br/><br/>     这些菜谱超链接的网页。还是为了方便起见,让我们想象这四个包含超链接的网页是整个互联网上仅有的链接到两个菜谱网页之<br/><br/>     一的网页。图中底部画线的文字就代表超链接,而箭头则表示链<br/><br/>     接的指向。<br/><br/>     图11 超链接把戏的原理。上面显示了6个网页,每个框都代表1个网页。其中2个<br/><br/>     网页是炒蛋菜谱,其余4个网页都有这些菜谱的超链接。超链接把戏认为伯特的网页<br/><br/>     比欧尼的网页排名高,因为伯特有3个链入链接(incoming link),而欧尼的只有1<br/><br/>     个<br/><br/>     问题是,这两个“命中”哪个应该有更高的排名,是伯特还<br/><br/>     是欧尼?人们在阅读链接这两份菜谱的网页并做出评价时不会有<br/><br/>     太大的问题。看起来这两份菜谱都很合理,但人们对伯特菜谱的<br/><br/>     反响要更为热烈一些。因此,在没有给出其他信息的情况下,伯<br/><br/>     特的菜谱比欧尼的菜谱排名更高可能会更合理。<br/><br/>     不幸的是,计算机并不擅长理解网页的真实意思,因此搜索<br/><br/>     引擎检查这四个链接“命中”的网页,并对每份菜谱获推荐的强烈程度进行评估也不太可能。另外,计算机在计算方面非常优<br/><br/>     秀。一种简单方法就是只计算链接每份菜谱的网页数——在这个<br/><br/>     例子中,1个网页链接欧尼的菜谱,3个网页链接伯特的菜谱——<br/><br/>     并根据这些菜谱的链入链接数对菜谱排名。当然,这种方法远不<br/><br/>     如让人阅读所有页面并手动排名精确,但它无疑是一种有用的方<br/><br/>     法。如果你没有其他信息,一个网页的链入链接数可能成为该网<br/><br/>     页“有用性”或“权威性”的指标。在这个例子中,伯特的菜谱<br/><br/>     得分为3,欧尼的菜谱得分为1,因此在搜索引擎向用户展示的结<br/><br/>     果中,伯特的网页排名比欧尼的高。<br/><br/>     你可能已经发现了一些在排名上使用这种超链接把戏的问<br/><br/>     题。一个很明显的问题就是,有时候链接被用来显示差网页,而<br/><br/>     非好网页。比如,假设有个链接欧尼菜谱的网页上写着:“我试<br/><br/>     了下欧尼的菜谱,很糟糕。”像这样批评而非推荐一个网页的链<br/><br/>     接,的确会导致超链接把戏将网页的排名拔高。不过,在现实<br/><br/>     中,超链接更多是用于推荐而非批评。因此,尽管有这个明显的<br/><br/>     缺陷,超链接把戏仍然很有用。<br/><br/>     权重把戏<br/><br/>     你可能已经在想,为什么要对网页的所有链入链接一视同<br/><br/>     仁,来自专家的推荐肯定就要比“菜鸟”的推荐更有价值吗?要<br/><br/>     细致地理解这一点,我们就要继续研究上面的炒蛋例子,不过研<br/><br/>     究的是另一组链入链接。下页的图对链入链接进行了重新设置:<br/><br/>     现在,伯特和欧尼菜谱的链入链接数相等了(只有一个),但欧尼的链入链接来自我的主页,伯特的则来自著名主厨艾利斯·沃<br/><br/>     特斯(Alice Waters)。<br/><br/>     如果没有其他信息,你更喜欢哪份菜谱?很显然,选择由一<br/><br/>     位著名主厨推荐的菜谱,要比选择由一名计算机科学相关书籍作<br/><br/>     者推荐的菜谱更好。我们称这一基本原则为“权重把戏”(The<br/><br/>     Authority Trick):来自高权重网页的链接排名要比来自低权<br/><br/>     重网页链接的排名高。<br/><br/>     图12 权重把戏的原理。这里显示了四个网页:两个炒蛋菜谱网页和两个链接菜<br/><br/>     谱的网页。其中一个链接来自本书作者(不是著名主厨),而另一个链接来自著名主<br/><br/>     厨艾利斯·沃特斯的主页。权重把戏将伯特的网页排在欧尼的菜谱之前,因为伯特的<br/><br/>     链入链接权重比欧尼的链入链接权重大<br/><br/>     这个原则很好,但其目前展示的形式对搜索引擎而言毫无用<br/><br/>     处。计算机如何才能自动判定艾利斯·沃特斯在炒蛋方面比我更<br/><br/>     具有权威性呢?有个想法也许会对此有所帮助:让我们把超链接把戏和权重把戏结合起来。所有网页的初始权重值(Authority<br/><br/>     Score)都是1,但如果一个网页有链入链接,在计算该网页权重<br/><br/>     时就要加入指向其网页的权重。也就是说,如果X和Y网页链接Z<br/><br/>     网页,那么Z网页的权重就是X网页和Y网页权重相加的值。<br/><br/>     下面的图详细地解释了如何计算这两个炒蛋菜谱网页的权重<br/><br/>     值。终值显示在圆圈中。图中有两个网页链接我的主页——这些<br/><br/>     网页本身没有链入链接,因此权重值为1。我的主页的权重值是<br/><br/>     所有链入链接权重值的总和,相加得2。艾利斯·沃特斯的主页<br/><br/>     有100个链入链接,每个链入链接的权重值为1,因此它的权重是<br/><br/>     100。欧尼的菜谱只有一个链入链接,但这个链入链接的权重值<br/><br/>     是2,因此将其所有链入链接的权重值相加(这个例子中只有一<br/><br/>     个数可加),能得出欧尼菜谱网页的权重值为2。伯特菜谱网页<br/><br/>     也只有一个链入链接,但其权重值为100,因此伯特菜谱网页的<br/><br/>     权重值为100。而因为100大于2,所以伯特的网页排名要比欧尼<br/><br/>     的高。图13 对两个炒蛋菜谱网页权重值的简单计算。权重值显示在圆圈中<br/><br/>     随机访问者把戏<br/><br/>     就自动计算权重值来说,我们似乎拥有了一个真正奏效的策<br/><br/>     略,无须计算机真正地理解网页内容。不幸的是,这种方法有个<br/><br/>     大问题。超链接很有可能形成被计算机科学家称为“循<br/><br/>     环”(cycle)的东西。循环指访问者可以通过点击超链接返回<br/><br/>     出发时的网页。<br/><br/>     下图就是个例子。图中有A、B、C、D、E五个网页。如果从A<br/><br/>     开始,我们可以通过A访问B,然后又从B访问E,而我们从E又能点回A,也就是回到了出发点。这也意味着A、B和E三个网页组成<br/><br/>     了一个循环。<br/><br/>     图14 超链接循环的一个例子。网页A、B和E组成了一个循环,你可以从A开始,点击到B,然后到E,再返回出发点A<br/><br/>     看来,在遇到循环时,目前权重值的定义(将超链接把戏和<br/><br/>     权重把戏结合起来)就碰到大麻烦了。看看在这个特例中会发生<br/><br/>     什么事情。网页C和D没有链入链接,因此其权重值为1。网页C和<br/><br/>     D都链向网页A,因此A的权重值是网页C和D权重值的和,也就是<br/><br/>     1+1=2。B网页从A获得的权重值为2,而E又从B获得权重值2。<br/><br/>     (这里谈到的情况都由下图左侧部分所体现。)但现在A的权重<br/><br/>     值要更新了:A从C和D各得到权重值1,但A也从E得到权重值2,相加为4。于是B的权重值也需要更新:从A获得权重值4。然后E<br/><br/>     的权重值也要更新,因为它从B获得了权重值4。(现在谈到的情<br/><br/>     况都由下图右侧部分所体现。)依此类推:于是A的权重值变为<br/><br/>     6,B变为6,E变为6,于是A的权重值又变为8……随着循环进<br/><br/>     行,网页的权重值会一直增加。图15 循环造成的问题。网页A、B和E永远需要更新,因此它们的权重值会一直增<br/><br/>     加下去<br/><br/>     这样计算权重值,会产生“鸡生蛋还是蛋生鸡”的问题。如<br/><br/>     果我们知道A网页真正的权重值,我们就能计算B网页和E网页的<br/><br/>     权重值。而如果我们知道B网页和E网页真正的权重值,我们就能<br/><br/>     计算A网页的权重值。但由于这些网页彼此依赖,这样计算似乎<br/><br/>     根本行不通。<br/><br/>     幸运的是,我们可以通过被称为随机访问者把戏(The<br/><br/>     Random Surfer Trick)的技术解决这个“鸡生蛋还是蛋生<br/><br/>     鸡”的问题。注意:对随机访问者把戏的初始描述,和到目前为<br/><br/>     止探讨的超链接及权重把戏没有任何关联。一旦了解了随机访问<br/><br/>     者把戏的基本原理,我们就会做一些分析,揭示其令人瞩目的品<br/><br/>     质:随机访问者把戏结合了超链接及权重把戏令人喜爱的属性,但在出现超链接循环时也行得通。<br/><br/>     这个把戏从假想一个随机访问互联网的人开始。确切地说,访问者随机从万维网上的一个网页开始访问,然后检查该网页上<br/><br/>     的所有超链接,之后随机挑选出其中一个超链接进行点击。随<br/><br/>     后,用户再检查打开的新网页,并随机选择一个超链接打开。这个过程会持续进行,每个网页都是通过随机选择前一个网页上的<br/><br/>     链接被打开的。图16就是个例子。在这个例子中,我们假设整个<br/><br/>     万维网只有16个网页。框代表网页,箭头代表网页之间的超链<br/><br/>     接。我们在其中标记了四个网页以便稍后进行参考。被访问者访<br/><br/>     问的网页用灰色表示,黑色箭头代表访问者点击的超链接,虚线<br/><br/>     箭头代表随机重新开始访问,这个在之后会讲到。<br/><br/>     整个过程有一个转折点:每次访问一个网页时,都有一个固<br/><br/>     定的重新访问概率(大概是15%),让访问者不从已有的超链接<br/><br/>     中挑选一个并点击。相反,访问者会重新开始这一过程,从互联<br/><br/>     网上随机选择一个网页点击。你也可以认为访问者有15%的概率<br/><br/>     对任何已有网页厌倦,导致其点击另一组链接,这么想也许会有<br/><br/>     帮助。要想找些例子,请仔细观察图16。这个特定的访问者从网<br/><br/>     页A开始,在对网页B厌倦前连续点击了三个随机超链接,并在网<br/><br/>     页C重新开始。在下次重新开始前,访问者又点击了两个随机超<br/><br/>     链接。(顺便说一句,本章中所有随机访问者例子中的重新开始<br/><br/>     概率都为15%,这也是谷歌联合创始人拉里·佩奇和谢尔盖·布<br/><br/>     林在描述其搜索引擎原型的原始论文中使用的值。)<br/><br/>     用计算机模拟这一过程很容易。我为此写了一个程序并运行<br/><br/>     了它,直到访问者访问了1 000个网页。(当然,这并不意味着<br/><br/>     是1 000个不重复的网页。对同一网页的多次访问也被纳入了计<br/><br/>     算当中,在这个例子中,所有网页都被访问了多次。)这1 000<br/><br/>     次模拟访问的结果显示在图17的上图中。你可以看到,网页D的<br/><br/>     访问次数最多,有144次。图16 随机访问者模式。被访问者访问的网页用灰色表示。虚线箭头代表随机重<br/><br/>     新开始访问(restart);实线箭头从网页A开始,指向随机选择的超链接,并被两个<br/><br/>     随机重新开始访问箭头打乱<br/><br/>     就像民意调查一样,我们可以通过增加随机样本的数目来提<br/><br/>     高模拟精度。我重新运行了一次模拟,直到访问者访问了100万<br/><br/>     个网页。(也许你会想这花了多长时间,在我电脑上运行只花了<br/><br/>     不到半秒!)考虑到访问量如此巨大,我们还是用百分比表示结<br/><br/>     果更好。这也就是你将在图17的下图中看到的情形。和之前的结<br/><br/>     果一样,网页D的访问次数最频繁,占总访问量的15%。<br/><br/>     随机访问者模型和权重把戏之间有什么联系可以被我们用于<br/><br/>     网页排名呢?从随机访问者模拟中计算得出的百分比,正好就是<br/><br/>     我们在衡量一个网页的权重时所需要的。因此,让我们将网页的<br/><br/>     访问者权重值(Surfer Authority Score)定义为一名随机访问者访问该网页的时间比例。值得注意的是,访问者权重值能和前<br/><br/>     两个对网页重要性进行排名的把戏配合良好。我们会逐一审视这<br/><br/>     些把戏。<br/><br/>     首先,让我们来审视一下超链接把戏:超链接把戏的主要思<br/><br/>     想是,一个有许多链入链接的网页应该有高排名。这在随机访问<br/><br/>     者模型中也适用,因为一个有许多链入链接的网页被访问的概率<br/><br/>     较大。图17下图中的网页D就是个好例子:它有五个链入链接<br/><br/>     ——比模拟中的其他网页都多——访问者权重值也最高<br/><br/>     (15%)。<br/><br/>     其次,让我们来看看权重把戏。权重把戏的主要思想是,和<br/><br/>     来自低权重网页的链入链接相比,一个来自高权重网页的链入链<br/><br/>     接应该更能证明一个网页的排名。随机访问者模型也包含这一<br/><br/>     点。为什么?因为和一个来自不知名网页的链接相比,访问者更<br/><br/>     有可能继续点击一个来自知名网页的链入链接。要在我们的模拟<br/><br/>     中找这样一个例子,请比较图17下图中的网页A和C:这两个网页<br/><br/>     都有一个链入链接,但网页A的访问者权重值要高得多(13%对<br/><br/>     2%),这主要取决于其链入链接的质量。<br/><br/>     注意,随机访问者模型能同时和超链接把戏及权重把戏相配<br/><br/>     合。换句话说,每个网页链入链接的质量和数量都会被纳入考虑<br/><br/>     范围。网页B就展示了这些:网页B的访问者权重值相对较高<br/><br/>     (10%),这得益于三个链入链接所在的网页拥有适中的访问者<br/><br/>     权重值,从4%到7%不等。图17 随机访问者模拟。上图:1 000次访问模拟中各网页的访问次数;下图:<br/><br/>     100万次访问模拟中各网页的访问次数占比随机访问者把戏的美妙之处在于,和权重把戏不同,不管超<br/><br/>     链接有没有形成循环,随机访问者把戏都能完美地运作。回到早<br/><br/>     前的炒蛋例子,我们能轻易地运行一次模拟随机访问。在数百万<br/><br/>     次访问之后,我的模拟产生了如下图所示的访问者权重值。请留<br/><br/>     意,和之前使用权重把戏进行的计算一样,伯特的网页访问者权<br/><br/>     重值要比欧尼的网页高很多(28%对1%)——尽管这两个网页都<br/><br/>     只有一个链入链接。因此,伯特的网页在网络搜索查询“炒<br/><br/>     蛋”中排名更高。<br/><br/>     图18 前文炒蛋例子中各网页的访问者权重值。伯特的菜谱网页和欧尼的菜谱网<br/><br/>     页都只有一个链入链接传入权重,但伯特的网页在网络搜索查询“炒蛋”时排名会更<br/><br/>     高现在让我们再转向前文中更困难的例子:对最初的权重把戏<br/><br/>     而言,由于超链接循环的存在,图14产生了一个不可解的问题。<br/><br/>     和前面一样,运行一次随机访问者的计算机模拟很容易,于是产<br/><br/>     生了如下图所示的访问者权重值。这一模拟判定的访问者权重值<br/><br/>     给出了网页的最终排名,这些排名会被搜索引擎在返回结果时使<br/><br/>     用:网页A排名最高,之后是B和E,C和D的排名同列最后一名。<br/><br/>     图19 早前超链接循环例子图14的访问者权重值。随机访问者把戏在计算合理的<br/><br/>     分值上没有问题,尽管存在一个循环(A→B→E→A)<br/><br/>     实践中的PageRank<br/><br/>     谷歌的两位联合创始人于1998年在他们著名的会议论文《解<br/><br/>     析大规模超文本网络搜索引擎》中描述了随机访问者把戏。通过和其他许多技术结合,这一把戏的变体仍被主流搜索引擎使用。<br/><br/>     不过,由于众多复杂因素,应用在现代搜索引擎中的实际技术和<br/><br/>     本章描述的随机访问者把戏略有不同。<br/><br/>     其中一个复杂因素直击PageRank的核心:超链接传输的合法<br/><br/>     权威性假设有时存在争议。我们先前已了解到,尽管超链接能代<br/><br/>     表批评而非推荐,但这在现实中并不是个很大的问题。另一个更<br/><br/>     加严重的问题是,人们可以滥用超链接把戏,人为地提高自己网<br/><br/>     页的排名。假设你运营着一个名为BooksBooksBooks.com的网站<br/><br/>     来售书,通过使用自动化技术,创建一大堆不同的网页,并让这<br/><br/>     些网页都链接BooksBooksBooks.com,做到这一切相对很容易。<br/><br/>     因此,如果搜索引擎像本章描述的一样来计算PageRank权重,BooksBooksBooks.com的权重值就能比其他书店高很多倍,进而<br/><br/>     有 更 高 的 排 名 和 更 多 的 销 售 额 , 而 这 都 不 是<br/><br/>     BooksBooksBooks.com应得的。<br/><br/>     搜索引擎称这种滥用为网络垃圾(Web Spam,这一术语是和<br/><br/>     电子邮件垃圾<e-mail spam>类比得来的:电子邮件收件箱中无<br/><br/>     用的信息,类似于充斥在搜索结果中无用的网页)。对所有搜索<br/><br/>     引擎而言,侦测并消除不同类型的网络垃圾是一直在进行的重要<br/><br/>     任务。比如,在2004年,微软的一些研究人员发现,逾30万个网<br/><br/>     页都只有1 001个网页链向它们——这是件非常令人生疑的事<br/><br/>     情。通过手动检查这些网页,研究人员发现,这些链入超链接绝<br/><br/>     大多数都是网络垃圾。<br/><br/>     因此,搜索引擎和网络垃圾制造者在进行一场“军备竞<br/><br/>     赛”。搜索引擎不断地尝试完善算法,以便返回真实排名。在完<br/><br/>     善PageRank算法的驱动下,大量针对其他使用互联网超链接结构进行网页排名的算法的学术和行业研究应运而生。这类算法通常<br/><br/>     被 称 为 基 于 链 接 的 排 名 算 法 ( Link-based Ranking<br/><br/>     Algorithms)。<br/><br/>     另一个复杂因素与PageRank计算的高效性有关。访问者权重<br/><br/>     值是通过运行随机模拟来计算的,但在整个互联网上运行这类模<br/><br/>     拟耗时太长,所以它们不能被实际运用。因此,搜索引擎并非通<br/><br/>     过模拟随机访问者来计算PageRank值:它们使用像随机访问者模<br/><br/>     拟一样给出相同答案的数学技巧,但计算成本要低很多。我们研<br/><br/>     究访问者模拟技术是因为它直观的吸引力,也因为它描述的是搜<br/><br/>     索引擎计算什么,而非如何计算。<br/><br/>     另外,值得一提的还有,商业搜索引擎中用来判定排名的算<br/><br/>     法要比PageRank这类基于链接的排名算法多得多。即便是在他们<br/><br/>     于1998年发表的描述谷歌的原始论文中,谷歌的联合创始人也提<br/><br/>     到了多种对搜索结果排名有贡献的功能。正如你所想的,这项技<br/><br/>     术已经进步了:在写作本书时,谷歌官网上声明“有超过200个<br/><br/>     信号”被用于评估一个网页的重要性。<br/><br/>     除了现代搜索引擎的众多复杂性,PageRank的核心思想——<br/><br/>     权威性网页通过超链接向其他网页传输权重——仍然有效。正是<br/><br/>     这一思想帮助谷歌击败了AltaVista,让谷歌从一家小型创业企<br/><br/>     业在几年后成长为“搜索之王”。若没有PageRank的核心思想,绝大多数搜索引擎查询都将被成千上万“命中”但不相关的“网<br/><br/>     页海洋”淹没。PageRank的确是一块算法瑰宝,能让“针”毫不<br/><br/>     费力地冒到“草垛”的顶端。第三章<br/><br/>     公钥加密<br/><br/>     ——用明信片传输秘密谁知道我这些最隐秘的事情?它们就藏在这个世界中。<br/><br/>     ——鲍勃·迪伦,《立约的女人》(Covenant Woman)<br/><br/>     人们喜欢传谣,也喜欢了解秘密。而由于加密的目的就是传<br/><br/>     输秘密,所以我们都是天生的密码员。但人类进行秘密沟通要比<br/><br/>     计算机容易。如果你想向朋友透露一个秘密,你只需在朋友耳边<br/><br/>     低语就行。计算机要做到这一点就不那么容易了。一台计算机没<br/><br/>     有办法“低声”向另一台计算机透露一张信用卡的卡号。如果计<br/><br/>     算机由互联网相连,它们既控制不了信用卡卡号的流向,又无法<br/><br/>     控制会有哪些计算机知道卡号。在本章,我们会探究计算机如何<br/><br/>     应对这一问题——通过运用永远都称得上很精巧、很具影响力的<br/><br/>     计算机科学思想之一:公钥加密。<br/><br/>     读到这里,你也许会想,为什么本章的标题中会提到“用明<br/><br/>     信片传输秘密”。下页的图会给出答案:可以通过明信片传递类<br/><br/>     比,展示公钥加密的威力。在现实生活中,如果你想要发送一份<br/><br/>     机密文件给某人,你自然会在发送前将文件封存在一个安全密封<br/><br/>     的信封内。这并不能保证机密性,但却是正确方向上的一个合理<br/><br/>     步骤。相反,如果在发送机密信息前,将机密信息写在明信片背<br/><br/>     面,很明显,这违背了机密性:任何一个接触过明信片的人(比<br/><br/>     如邮局工作人员)都只需查看明信片,就能读到这条消息。<br/><br/>     这也正是计算机在互联网上尝试相互进行机密通信时面临的<br/><br/>     问题。因为互联网上的所有信息都会通过无数被称为路由器的计算机,信息的内容可以为任何访问路由器的人所见,而这也包括<br/><br/>     潜在的恶意窃听者。因此,每一条离开你的计算机并进入互联网<br/><br/>     的数据,就好像写在明信片上一样!<br/><br/>     图20 明信片类比:很显然,通过邮政系统寄出一张明信片不能保证明信片内容<br/><br/>     的秘密性。基于同样的理由,如果没有恰当地加密,你从笔记本电脑上将一张信用卡<br/><br/>     的卡号发送给购物网站,很容易就会被一名窃听者窥探到<br/><br/>     针对这个明信片问题,你也许已经想到了一个快速补救方<br/><br/>     案。在将信息写到明信片上之前,我们为什么不使用密码对每条<br/><br/>     信息进行加密呢?实际上,如果你已经知道接收明信片的人,这<br/><br/>     个方法还能奏效,因为在过去某个时刻,你们就使用哪种密码已<br/><br/>     经达成一致。真正的问题出现在你给不认识的人寄明信片时。如果你在明信片上使用密码,邮局工作人员就不能读取你的消息,收信人当然也不能!公钥加密的真正威力在于,它允许你应用只<br/><br/>     有接收方才能解密的密码——除非你们不能就使用哪种密码达成<br/><br/>     一致。<br/><br/>     注意,计算机在和不“认识”的接收方通信时会面临相同的<br/><br/>     问题。比如,你第一次用信用卡在网上购物时,你的计算机必须<br/><br/>     将你的信用卡卡号传输给购物网站的服务器。但你的计算机之前<br/><br/>     从未和那个服务器联系过,因此这两台计算机在过去没有机会就<br/><br/>     密码达成一致。而它们之间尝试达成的任何协议都会被互联网上<br/><br/>     所有的路由器注意到。<br/><br/>     让我们回到明信片的类比。的确,这种情况听起来像个悖<br/><br/>     论:接收方看到的信息和邮局工作人员看到的一样,但接收方有<br/><br/>     某种手段能解码消息,而邮局工作人员却没有这种手段。公钥加<br/><br/>     密为这一悖论提供了一个解决方案。本章将解释其工作原理。<br/><br/>     用共享密钥加密<br/><br/>     让我们从一个非常简单的思想实验开始。我们将放弃明信片<br/><br/>     类比,用更简单的说法来代替:在一个房间内的口头交流。具体<br/><br/>     情况是,你和朋友阿诺德以及敌人伊芙待在一个房间里。你想要<br/><br/>     秘密地传输一条消息给阿诺德,但又不能让伊芙理解这条消息。<br/><br/>     这条消息可能是一张信用卡的卡号,但为方便起见,假设这是一<br/><br/>     个极其短的信用卡卡号,只是1到9之间的一个数字。而你只能通<br/><br/>     过大声说话和阿诺德联系,好让伊芙听到。不得偷偷摸摸地耍小<br/><br/>     把戏,比如小声说或传纸条。具体来说,让我们假设你试图传输的信用卡卡号为7。有一<br/><br/>     种方法可以让你达成目标:首先,尝试想一些阿诺德知道而伊芙<br/><br/>     不知道的数字。比如,你和阿诺德成为朋友很久了,从孩提时就<br/><br/>     生活在同一条街上。事实上,假设你们俩经常在你家前院玩耍,门牌号是愉快街322号。其次,假设伊芙并不是从小就认识你,特别是她不知道你和阿诺德过去经常玩耍的房屋地址。你就能对<br/><br/>     阿诺德说:“嘿,阿诺德,记得我在愉快街的家的门牌号吗?我<br/><br/>     们过去一起玩耍的地方。如果你用门牌号,加上我现在想到的信<br/><br/>     用卡卡号中的一个数,你会得到329。”<br/><br/>     现在,只要阿诺德能正确地记得房屋门牌号,他就可以通过<br/><br/>     将你告诉他的总数329和房屋门牌号相减,得到信用卡卡号。他<br/><br/>     用329减去322,结果是7,这也是你试图向他传输的信用卡卡<br/><br/>     号。同时,伊芙却不知道信用卡卡号是多少,尽管她能听到你跟<br/><br/>     阿诺德说的每个词。下图显示了整个过程。<br/><br/>     为什么这种方法能奏效?因为你和阿诺德有一样东西,也就<br/><br/>     是计算机科学家们所谓的共享密钥:数字322。因为你们俩都知<br/><br/>     道这个数字,但伊芙不知道,你就可以使用这个共享密钥秘密地<br/><br/>     传输任何数字,只要和共享密钥相加,说出总数,让另一方减去<br/><br/>     共享密钥即可。听到总数对伊芙没有任何用处,因为她不知道要<br/><br/>     减去哪个数字。图21 相加把戏:通过将消息7和共享密钥322相加,消息7被加密了。阿诺德可以<br/><br/>     通过减去共享密钥提取消息7,但伊芙却不能<br/><br/>     不管你是否相信,如果理解了这个简单的“相加把戏”——<br/><br/>     将一个共享密钥和一张信用卡的卡号这类私人消息相加——你就<br/><br/>     理解了互联网上绝大多数加密真正的运作原理!计算机不断地运<br/><br/>     用着这一把戏,但要真正实现保密性,还有一些细节需要注意。<br/><br/>     计算机使用的共享密钥要比房屋门牌号322长很多。如果密<br/><br/>     钥太短,任何窃听对话的人都可以试遍所有可能性。比如,假设<br/><br/>     我们使用相加把戏,用一个3位数房屋门牌号来加密一个真正的<br/><br/>     16位数信用卡卡号。注意,3位数房屋门牌号有999种可能,那么<br/><br/>     像伊芙这样窃听了对话的敌人可以列出一张包含所有999个可能<br/><br/>     数字的表,而其中肯定有一个数字是信用卡卡号。而计算机几乎<br/><br/>     不用费什么时间就能试遍999个信用卡卡号,因此为了共享密钥<br/><br/>     能起作用,我们需要用远长于3位数的数字来作为共享密钥。事实上,当你听到某种加密是一个特定位数的数字,比<br/><br/>     如“128位加密”时,这实际上说的是共享密钥的长度。共享密<br/><br/>     钥通常被称为“钥”,是因为它能用于解锁或“解密”一条消<br/><br/>     息。如果你解开了密钥数位的30%,这也就告诉了你密钥的大致<br/><br/>     数位。因为128的30%大约是38,我们就知道128位密钥是一个38<br/><br/>     位的数[1]。一个38位的数要比10的36次方还要大,而又因为这<br/><br/>     需要任何现存的计算机花费数十亿年时间来试遍这么多种可能<br/><br/>     性,所以一个38位数的共享密钥被认为非常安全。<br/><br/>     要想让这个简单相加把戏在现实生活中奏效还要克服一个困<br/><br/>     难:加法得出的结果能用于统计分析,这意味着一些人能通过分<br/><br/>     析你的大量加密消息来得到密钥。相反,被称为“分块密<br/><br/>     码”(Block Cipher)的现代加密技术使用了相加把戏的变体。<br/><br/>     首先,长消息被分解成固定大小(通常是10~15个字母)的<br/><br/>     小“块”。其次,和简单地将一“块”消息与密钥相加不同的<br/><br/>     是,每个“块”都会根据一系列固定规则转换数次。这些规则类<br/><br/>     似于加法,但会让消息和密钥更紧密地混合在一起。比如,规则<br/><br/>     可以是“将密钥的前半部分和这‘块’消息的后半部分相加,倒<br/><br/>     置结果,再将密钥的第二部分和这‘块’消息的前半部分相<br/><br/>     加”——不过在现实中,这些规则要更加复杂一些。现代分块密<br/><br/>     码基本上会进行10“轮”或更多类似操作,即操作列表会被反复<br/><br/>     应用。在转换的轮数足够多时,原始消息会真正地混合好,并能<br/><br/>     抵御统计攻击,但任何知道密钥的人都能用相反的步骤运行所有<br/><br/>     操作,以获得最初的、解密的消息。在写作本书时,最流行的分块密码是高级加密标准<br/><br/>     (Advanced Encryption Standard),或称AES。AES能配合多种<br/><br/>     不同配置使用,但标准配置是使用16个字母的“块”,配备128<br/><br/>     位密钥,进行10轮混合操作。<br/><br/>     公开建立一个共享密钥<br/><br/>     到目前为止,一切情况良好。我们已经知道互联网上绝大多<br/><br/>     数加密技术的运作原理:将消息分成“块”,使用加法把戏变体<br/><br/>     加密每个“块”。但这是加密简单的地方。难点在于一开始要建<br/><br/>     立一个共享密钥。在上面的例子中,在你和阿诺德及伊芙待的房<br/><br/>     间里,其实我们“作弊”了——我们利用了你和阿诺德从小玩到<br/><br/>     大的事实,因此阿诺德知道共享密钥(你家的房屋门牌号)而伊<br/><br/>     芙不可能知道。如果你、阿诺德和伊芙都是陌生人,我们怎么玩<br/><br/>     同样的游戏?你有没有办法和阿诺德建立一个伊芙不知道的共享<br/><br/>     密钥?(记住,不能作弊——你不能低声跟阿诺德说任何事情或<br/><br/>     给阿诺德一张伊芙看不到的纸条。所有沟通都必须公开。)<br/><br/>     乍一看,要做到这一点似乎不可能,但还是有个精巧的办法<br/><br/>     能解决这个问题。计算机科学家们称这一解决方案为迪菲–赫尔<br/><br/>     曼密钥交换(Diffie-Hellman Key Exchange),但我们把它称<br/><br/>     作颜料混合把戏(Paint-mixing Trick)。<br/><br/>     颜料混合把戏要理解这一把戏,我们先不管传输信用卡卡号的事,而是假<br/><br/>     设你想要分享的密钥是一种特殊颜色的颜料。(的确,这有点儿<br/><br/>     诡异,但我们很快会看到,用这种方法来思考这个问题非常有<br/><br/>     用。)现在假设你和阿诺德、伊芙待在一个房间内,每人都有大<br/><br/>     量不同的颜料桶。你们都拥有相同的颜色选择——有多种不同颜<br/><br/>     色,每个人都拥有多桶相同颜色的颜料。这样就不存在用完颜料<br/><br/>     的问题了。每一桶颜料都清楚地标示了其颜色,因此指导其他人<br/><br/>     混合不同颜色的颜料就很容易了:你只要说些如“将1桶‘天蓝<br/><br/>     色’颜料和6桶‘淡黄褐色’颜料及5桶‘碧绿色’颜料混合在一<br/><br/>     起”的话即可。但在每一块已知的色板(shade)上都有上百或<br/><br/>     上千种颜色,因此,不可能只通过看颜色就知道其中混合了哪些<br/><br/>     具体的颜色,也不可能通过试错发现混合颜色中加入了哪些具体<br/><br/>     的颜色,因为可以尝试的颜色太多了。<br/><br/>     现在要改变一下游戏规则。你们三人各占据房屋的一角,每<br/><br/>     个角落都出于隐私考虑加以屏障,你可以在其中存放颜料,在其<br/><br/>     他人看不到的情况下混合颜料。但沟通规则和之前一样:在你、阿诺德和伊芙之间的任何沟通都必须公开。你不能邀请阿诺德进<br/><br/>     入你的私人混合区域。另一条规则规定了你分享颜料混合配方的<br/><br/>     方式。你可以给屋内其他人一批颜料,但只能把颜料放到房间中<br/><br/>     央的地板上,等其他人来捡起它。这也意味着,你永远不能确定<br/><br/>     谁会捡起你放的颜料。最好的办法是,为每个人提供足够多的颜<br/><br/>     料,然后在房间中央留下数批分开的颜料。这样,任何想要你颜<br/><br/>     料的人都可以拿取。这条规则其实只是所有沟通都必须公开的补<br/><br/>     充:如果你给了阿诺德某种混合颜料,却没有给伊芙,你就和阿<br/><br/>     诺德进行了某种“私密”沟通,这违反了规则。记住,这个颜料混合游戏旨在解释如何建立一个共享密钥。<br/><br/>     在这时,你也许在想混合颜料和加密有什么关系,请不要着急。<br/><br/>     你将了解到一个令人惊奇的把戏,计算机能像互联网一样使用这<br/><br/>     一把戏在公共场合建立共享密钥!<br/><br/>     首先,我们要知道这个游戏的目标:让你和阿诺德都能制作<br/><br/>     相同的混合颜料,而不能让伊芙知道如何生产。如果你达成了这<br/><br/>     一目标,我们就能说你和阿诺德建立了一种“共享的秘密混合颜<br/><br/>     料”。你可以随心所欲地进行尽可能多的公开对话,你也可以携<br/><br/>     带颜料桶多次往返于房间中央及你的私人混合区域之间。<br/><br/>     其次,我们要开始探访公钥加密背后精巧思想的旅程了。我<br/><br/>     们将颜料混合把戏的实施分为四步。<br/><br/>     第一步:你和阿诺德各自选择一种“私人颜色”。<br/><br/>     你的私人颜色与你最终将制造的共享秘密混合颜料不同,但<br/><br/>     它将是共享秘密混合颜料的成分之一。你可以选择任何一种颜色<br/><br/>     作为私人颜料,但你必须记住这种颜色。很显然,你的私人颜色<br/><br/>     几乎肯定会和阿诺德的私人颜色不同,因为可供选择的颜色太多<br/><br/>     了。假设你选了淡紫色作为私人颜色,阿诺德选了深红色作为私<br/><br/>     人颜色。<br/><br/>     第二步:选择一种新的不同的颜色成分并公开宣布,我<br/><br/>     们称这种颜色为“公开颜色”。和之前一样,你可以选择任何颜色。假设你宣布的公开颜色<br/><br/>     是雏菊黄。注意只能是你有一种公开颜色(而不是你和阿诺德各<br/><br/>     选一种公开颜色),伊芙自然也知道这种公开颜色,因为你公开<br/><br/>     宣布了。<br/><br/>     第三步:你和阿诺德各用一桶公开颜色和一桶私人颜色<br/><br/>     制造一种混合颜色。这就是你的“公开 – 私人混合颜<br/><br/>     色”。<br/><br/>     很显然,阿诺德的公开–私人混合颜色会和你的不同,因为<br/><br/>     他的私人颜色和你的不同。如果继续使用上面的例子,你的公开<br/><br/>     –私人混合颜色会包含一桶淡紫色和一桶雏菊黄,而阿诺德公开<br/><br/>     –私人混合颜色会包含一桶深红色和一桶雏菊黄。<br/><br/>     到这时,你和阿诺德会想给彼此公开–私人混合颜色的样<br/><br/>     品,但记住,直接给房间中的一个人混合颜料是违反规则的。给<br/><br/>     其他人一种混合颜色的唯一方法是制作数批该种颜料,并把它们<br/><br/>     放到房间中央,以便任何想要的人拿取。这也正是你和阿诺德所<br/><br/>     做的:你们俩都制作了数批公开–私人混合颜色,并把它们放到<br/><br/>     房间中央。如果伊芙想要的话,她可以拿走一两批,但我们很快<br/><br/>     就会了解到,这些颜料对伊芙没有任何用处。下页的图显示了颜<br/><br/>     料混合把戏第三步之后的情况。<br/><br/>     现在到达关键点了。如果在这时仔细想一会儿,你可能就会<br/><br/>     知道最后的把戏能让你和阿诺德制造出同一种共享的秘密混合颜<br/><br/>     色,而不让伊芙知道秘密。答案如下:图22 数字混合把戏第三步:任何想要的人都能获取公开–私人数字<br/><br/>     第四步:你选取一批阿诺德的公开–私人混合颜色,拿<br/><br/>     回自己的角落。现在加入一桶私人颜色。同时,阿诺德选取<br/><br/>     一批你的公开 – 私人混合颜色,拿回他的角落,在那里,他再加入一桶他的私人颜色。<br/><br/>     神奇吧,你们俩制作了同样的混合颜色!让我们来检验一<br/><br/>     下:你将自己的私人颜色(淡紫色)加入阿诺德的公开–私人混<br/><br/>     合颜色(深红色和雏菊黄),得到的最终混合颜色是:一桶淡紫<br/><br/>     色、一桶深红色和一桶雏菊黄。阿诺德最终得到的混合颜色呢?他将自己的私人颜色(深红色)加入你的公开–私人混合颜色<br/><br/>     (淡紫色和雏菊黄),得到的最终混合颜色是:一桶深红色、一<br/><br/>     桶淡紫色和一桶雏菊黄。这正和你得到的最终混合颜色一样,也<br/><br/>     恰好是一种共享秘密混合颜色。下面的图显示了颜料混合把戏最<br/><br/>     后一步的情形。<br/><br/>     图23 颜料混合把戏第四步:只有你和阿诺德能制作这种共享秘密颜色,如箭头<br/><br/>     所示混合颜色组合<br/><br/>     那伊芙呢?为什么她不能制作这种共享秘密混合颜色呢?原<br/><br/>     因是她不知道你或阿诺德的私人颜色,而她至少需要其中一种来<br/><br/>     制作共享秘密混合颜色。你和阿诺德打败了她,因为你从未在房间中央公开过自己的私人颜色。相反,你在公开前将自己的私人<br/><br/>     颜色和公开颜色混合在一起,而伊芙没有办法“分开”公开–私<br/><br/>     人混合颜色,也就不能获得其中一种私人颜色的纯正样本。<br/><br/>     图像<br/><br/>     因此,伊芙只能获取两种公开–私人混合颜色。如果她将1<br/><br/>     桶你的公开–私人混合颜色和1桶阿诺德的公开–私人混合颜色<br/><br/>     混合在一起,结果是形成1桶深红色、1桶淡紫色和2桶雏菊黄。<br/><br/>     换句话说,和共享秘密混合颜色相比,伊芙的混合颜色多了1份<br/><br/>     雏菊黄。她的混合颜色太黄了,而因为没有办法“分开”颜料,她不能移除多余的黄色。你也许会想,伊芙可以通过加入更多深<br/><br/>     红色和淡紫色来达到目的,但要记住,伊芙不知道你的私人颜<br/><br/>     色,所以她不会知道还需要加入的颜色。她只能加入深红色配雏<br/><br/>     菊黄的组合或淡紫色配雏菊黄的组合,而这会导致她的混合颜色<br/><br/>     太黄。<br/><br/>     用数字进行颜料混合把戏<br/><br/>     如果你理解了颜料混合把戏,你就会理解计算机在互联网上<br/><br/>     建立共享密钥的核心机制。当然,它们并不真的使用颜料。计算<br/><br/>     机使用的是数字,而要混合数字,它们就会运用数学。计算机实<br/><br/>     际使用的数学并不会太复杂,但也足以复杂到让人第一眼看上去<br/><br/>     就会感到困惑。因此,要想理解共享密钥如何在互联网上建立,下一步我们将用到“伪装”数学。真正的要点在于,要将颜料混<br/><br/>     合把戏转化成数字,我们就需要单向操作(One-way Action):<br/><br/>     可以做一些事情,但不能取消做过的事。颜料混合把戏中的单向操作是“混合颜料”。将一些颜料混合起来形成一种新颜色很容<br/><br/>     易,但要“分开”它们并获得原来的颜料则不可能。这也是颜料<br/><br/>     混合是单向操作的原因。<br/><br/>     我们在前面提到过将会用到“伪装”数学。下面就是我们<br/><br/>     要“伪装”的:将两个数相乘是一项单向操作。我敢肯定,你已<br/><br/>     经意识到了,这绝对是个借口。乘法的反面是除法,只需要用除<br/><br/>     法就能惊奇地取消乘法。比如,如果我们将数字5乘以7,就能得<br/><br/>     到35。要取消这个乘法很容易,只要将35除以7就可以了,这会<br/><br/>     得到我们一开始时的数字5。<br/><br/>     但除此以外,我们将坚持使用这一“伪装”,在你、阿诺德<br/><br/>     和伊芙之间玩另一个游戏。这一次,我们将假设你们都知道如何<br/><br/>     将数相乘,但你们都不知道如何用一个数除以另一个数。目标和<br/><br/>     前面的游戏几乎一样:你和阿诺德试图建立一个共享密钥,但这<br/><br/>     次共享密钥将是一个数字,而非一种颜料。此前的沟通规则也适<br/><br/>     用:所有联系必须公开进行,这样伊芙就能听到你和阿诺德之间<br/><br/>     的任何对话。<br/><br/>     好,现在我们要做的事情就是将颜料混合把戏转换成数字。<br/><br/>     第一步:和选择一种“私人颜色”不同的是,你和阿诺<br/><br/>     德要各自选择一个“私人数字”。<br/><br/>     假设你选择了4,阿诺德选择了6。现在回想一下颜料混合把<br/><br/>     戏剩余的步骤:宣布公开颜色,制作公开–私人混合颜色,公开<br/><br/>     地将你的公开–私人混合颜色与阿诺德的公开–私人混合颜色交换,最后将你的私人颜色加入阿诺德的公开–私人混合颜色,以<br/><br/>     获得共享秘密颜色。要理解如何将这些步骤转换成数字,并用乘<br/><br/>     法作为单向操作取代颜料混合并不太难。在继续往下读之前,先<br/><br/>     花几分钟看看你能否自行理解这个例子。<br/><br/>     理解这个解决方案并不太难。你和阿诺德都选择了自己的私<br/><br/>     人数字(4和6),下一步就是:<br/><br/>     第二步:你们其中一个人宣布“公开数字”(取代颜料<br/><br/>     混合把戏中的公开颜色)。<br/><br/>     假设你选择了7作为公开数字。<br/><br/>     颜料混合把戏的下一步是制作一份公开–私人混合颜色。但<br/><br/>     我们已经决定,用将数字相乘的方式来代替混合颜料。因此,你<br/><br/>     要做的就是:<br/><br/>     第三步:将你的私人数字(4)和公开数字(7)相乘,得到“公开–私人数字”28。<br/><br/>     你可以公开地宣布,这样阿诺德和伊芙就都知道了你的公开<br/><br/>     –私人数字是28(无须再携带颜料桶了)。阿诺德对自己的私人<br/><br/>     数字做了同样的事:他将自己的私人数字和公开数字相乘,并宣<br/><br/>     布他的公开–私人数字是42。下页的图显示了整个流程到达这一<br/><br/>     点的情形。还记得颜料混合把戏的最后一步吗?你拿走阿诺德的公开–<br/><br/>     私人混合颜色,加入一桶你的私人颜色,以制作共享秘密颜色。<br/><br/>     这里发生的事情也一模一样,是用乘法代替颜料混合。<br/><br/>     图24 数字混合把戏第三步:任何想要的人都能获取公开–私人数字<br/><br/>     第四步:你把阿诺德的公开–私人数字(42)和你的私<br/><br/>     人数字(4)相乘,结果是共享秘密数字168。<br/><br/>     同时,阿诺德用你的公开–私人数字28和他的私人数字6相<br/><br/>     乘,并令人惊讶地得到了共享秘密数字168。最终结果显示在下页图中。<br/><br/>     事实上,当你用正确的方法思考时,这一点儿都不令人惊<br/><br/>     讶。阿诺德和你都制作出了相同的共享秘密颜色的原因是,你将<br/><br/>     相同的三种原始颜色混合在了一起,但使用了不同的顺序:你们<br/><br/>     俩各自保留了一种私人颜色,把它和由其他两种颜料组成的公开<br/><br/>     混合颜料组合在一起。同样的事也发生在数字上。你们俩通过将<br/><br/>     同样的三个数4、6和7相乘,得到了相同的共享密钥。(你可以<br/><br/>     自己查证,4×6×7=168。)但你能达到这一目标,是通过用私<br/><br/>     人数字4和由6乘7得出的公开混合数字“混合”(相乘)得出<br/><br/>     的,而阿诺德也宣布了这个混合数字。从另一个角度看,阿诺德<br/><br/>     通过用私人数字6和由4乘7得出的公开混合数字“混合”(相<br/><br/>     乘)得出共享密钥,而你也宣布了这个混合数字。图25 数字混合把戏第四步:只有你和阿诺德能得到共享密钥数字,即将途中箭<br/><br/>     头所示的数字相乘<br/><br/>     就和我们在颜料混合把戏中做的一样,让我们来验证伊芙不<br/><br/>     能得到共享密钥。每个公开–私人数字的值在宣布时都能被伊芙<br/><br/>     听到。她听到你说28,阿诺德说42。她还知道公开数字是7。因<br/><br/>     此,如果伊芙知道如何做除法,她就能马上知道你所有的密钥,她只需观察到28÷7=4和42÷7=6即可。而她可以继续通过计算<br/><br/>     4×6×7=168算出共享密钥。不过,幸运的是,我们在游戏中使<br/><br/>     用的是“伪装”数学:我们假设乘法是一种单向操作,因此伊芙<br/><br/>     不知道如何相除。于是她被数字28、42和7难住了。她可以将其<br/><br/>     中一些数相乘,但结果和共享密钥无关。比如,如果她将28×42=1 176,那就大错特错了。就和颜料混合游戏中她的结果<br/><br/>     太黄了一样,在这里,她的结果中有太多7。共享密钥中只有一<br/><br/>     个7,因为168=4×6×7。但伊芙想要破解的密钥要素中有两个<br/><br/>     7,因为1 176=4×6×7×7。她也没有办法去掉多余的7,因为她<br/><br/>     不知道如何做除法。<br/><br/>     现实生活中的颜料混合把戏<br/><br/>     我们现在已经讲完了计算机在互联网上建立共享密钥所需的<br/><br/>     所有基本概念。使用数字的颜料混合机制唯一的缺陷是,它使用<br/><br/>     的是“伪装”数学,我们在其中假设没有任何一方能做除法。要<br/><br/>     完成整个流程,我们就需要一个在现实生活中容易做到(比如颜<br/><br/>     料混合),但在实际中又不可能取消(比如分离颜料)的数学操<br/><br/>     作。当计算机在现实生活中进行这些操作时,混合操作就是离散<br/><br/>     指数(Discrete Exponentiation),而分离操作则被称为离散<br/><br/>     对数(Discrete Logarithm)。由于还没有一种方法能让计算机<br/><br/>     高效地计算离散对数,离散指数就成了我们寻找的那类单向操<br/><br/>     作。要恰当地解释离散指数,我们就需要两个简单的数学概念。<br/><br/>     我们还需要写几个公式。如果你不喜欢公式,请直接忽略余下的<br/><br/>     部分——你几乎了解了和这个主题有关的所有东西。另外,如果<br/><br/>     你真的想知道计算机会如何做这件神奇的事,就接着往下读。<br/><br/>     我们需要的第一个重要的数学概念被称为钟算(Clock<br/><br/>     Arithmetic)。这倒是我们都熟悉的东西:钟表上有12个数字,每次当时针路过12时,都会从1开始重新计数。一个从10点钟开<br/><br/>     始、持续4小时的活动会在2点钟结束,也就是说,在这个12小时钟系统中,10+4=2。在数学中,钟算也是这样运行的,除了两个<br/><br/>     细节:(1)钟的大小可以是任何数(而非一座普通的钟上熟悉<br/><br/>     的12个数字);(2)数字从0而不是从1开始计数。<br/><br/>     下图中的例子用的是大小为7的钟。注意,钟上的数字是0、1、2、3、4、5和6。用大小为7的钟做钟算,只要像平常一样将<br/><br/>     数字相加再相除即可,不过不管结果如何,你只要取除以7所得<br/><br/>     的余数即可。比如计算12+6,我们首先像平常一样相加,得到<br/><br/>     18。然后我们注意到18中有两个7(即14),余4。因此最终答案<br/><br/>     是:<br/><br/>     图26 左图:当钟大小为7时,数字12被简化为数字5——从0开始,按图中箭头所<br/><br/>     示顺时针方向计算12个单位;右图:钟大小仍为7,我们发现12+6=4——从5开始,这<br/><br/>     也是左图结束的地方,再在顺时针方向添加另外6个单位<br/><br/>     12+6=4(钟大小为7)<br/><br/>     在下面的例子中,我们将钟大小调为11。(稍后将讨论到,现实应用中的钟大小要大很多。我们使用大小偏小的钟是为了让<br/><br/>     解释尽可能简单。)在将结果除以11后取余并不太难,因为11的倍数都是像66和88这样重复的数字。下面是几个用钟大小为11进<br/><br/>     行计算的例子:<br/><br/>     7+9+8=24=2(钟大小为11)<br/><br/>     8 × 7=56=1(钟大小为11)<br/><br/>     我们需要的第二个数学概念是幂函数(Power Notation)。<br/><br/>     这个概念一点儿也不花哨,就是写下许多相同数字相乘的快捷方<br/><br/>     法。和写下6×6×6×6不同的是,你可以写成64,这就是指6乘<br/><br/>     以本身4次。你可以将幂函数和钟算结合起来。比如:<br/><br/>     34=3 × 3 × 3 × 3=81=4(钟大小为11)<br/><br/>     72=7 × 7=49=5(钟大小为11)<br/><br/>     下页图中的数据显示了钟大小为11时数字2、3和6的前10个<br/><br/>     幂。这在我们将要研究的例子中非常有用。在继续深入前,请你<br/><br/>     确保自己认可这张表格的生成方式。让我们来看看最后一栏。这<br/><br/>     一栏的第一项是6,也就是61。下一项代表62,即36,但由于我<br/><br/>     们使用的钟大小为11,36比33大3,因此这一项是3。要计算这一<br/><br/>     栏的第三项,你也许会认为我们要计算63=6×6×6,但有个更简<br/><br/>     单的方法。我们已经用自己感兴趣的钟大小计算了62,结果是<br/><br/>     3。要得到63,我们只需要将先前的结果乘以6,也就是<br/><br/>     3×6=18=7(钟大小为11)。下一项是7× 6=42=9(钟大小为<br/><br/>     11),依此类推,直到该栏最后一项。最后,我们终于要准备建立计算机在现实生活中使用的一个<br/><br/>     共享密钥了。和之前一样,你和阿诺德将尝试分享一个密钥,而<br/><br/>     伊芙在窃听并试图算出密钥。<br/><br/>     第一步:你和阿诺德各自单独选择一个私人数字。图27 此处显示了钟大小为11时数字2、3和6的前10个幂。每项都能通过一些非常<br/><br/>     简单的算术从上一项中被算出为保证数学尽可能简单,我们将在这个例子中使用非常小的<br/><br/>     数字。因此,假设你选择8作为私人数字,而阿诺德选择9。这两<br/><br/>     个数字——8和9——都不是共享密钥,而是像你在颜料混合把戏<br/><br/>     中选择的私人颜色,这些数字将被用作“混合”一个共享密钥的<br/><br/>     成分。<br/><br/>     第二步:你和阿诺德公开就两个公开数字达成一致——<br/><br/>     钟大小(本例中使用11)和另一个被称为基数的数字(选2<br/><br/>     为基数)。<br/><br/>     这些公开数字——11和2——像公开颜色一样,你和阿诺德<br/><br/>     在颜料混合把戏一开始就对此达成了一致。注意,颜料混合类比<br/><br/>     与本例有点儿不同:在颜料混合中,我们只需一种公开颜色,而<br/><br/>     在这个例子中,我们需要两个公开数字。<br/><br/>     第三步:通过使用幂符号和钟算,你和阿诺德各自将自<br/><br/>     己的私人数字和公开数字相混,分别得到一个公开–私人数<br/><br/>     字(public–private number,PPN)。<br/><br/>     具体来说,混合是按照公式完成的:<br/><br/>     PPN=base私人数字(钟大小)<br/><br/>     这个公式用文字写出来可能会显得有点儿诡异,但实际却很<br/><br/>     简单。在我们的例子中,我们能通过参考上一页图中的数据来得出答案:<br/><br/>     你的PPN=28=3(钟大小为11)<br/><br/>     阿诺德的PPN=29=6(钟大小为11)<br/><br/>     在这一步之后,你可以在下页的图中查看这一步。这些公开<br/><br/>     –私人数字正相当于你在颜料混合把戏第三步中制作的“公开–<br/><br/>     私人混合颜色”。在那一步中,你将一桶公开颜色和一部分你的<br/><br/>     私人颜色相混合,制作了你的公开–私人混合颜色。在这里,你<br/><br/>     使用幂符号和钟算将自己的私人数字和公开数字相混合。<br/><br/>     第四步:你和阿诺德各自单独获得对方的公开–私人数<br/><br/>     字,再将其与自己的私人数字相混合。<br/><br/>     这可以按照下面的公式完成:<br/><br/>     共享密钥=其他人的PPN私人数字 (钟大小)<br/><br/>     和前面的公式一样,这用文字写出来会显得有点儿诡异,但<br/><br/>     通过参考前一页的表格,很容易就能得到答案:<br/><br/>     你的共享密钥=68=4(钟大小为11)<br/><br/>     阿诺德的共享密钥=39=4(钟大小为11)<br/><br/>     最终解决方案将显示在第69页的图中。如此,你的共享密钥和阿诺德的共享密钥相同(这个例子中<br/><br/>     是4)。取得这个结果是依靠了例子中的一些复杂算术,但基本<br/><br/>     概念和前面一样:尽管你按照不同的顺序混合了各种成分,但你<br/><br/>     和阿诺德都使用了相同的成分,因此也得到了相同的共享密钥。<br/><br/>     和这个把戏的早前版本一样,伊芙被排除在外。她知道这两<br/><br/>     个公开数字(2和11),她也知道这两个公开–私人数字(3和<br/><br/>     6)。但她不能使用任何知识来计算共享密钥数字,因为她不能<br/><br/>     获取你和阿诺德持有的秘密成分(私人数字)。<br/><br/>     图28 现实生活数字混合第三步:任何想要公开–私人数字(3和6)的人——使<br/><br/>     用幂和钟算计算得出——都可以获取到。3下面的“28”提醒了我们3是如何计算的,但3=28使用的钟大小为11这个事实却并未公开。类似的,6下面的“29”也仍然保持<br/><br/>     私密<br/><br/>     实践中的公钥加密<br/><br/>     颜料混合把戏的最终版本——运用幂和钟算混合数字——就<br/><br/>     是计算机在互联网上建立共享密钥的实践方法之一。本章描述的<br/><br/>     方法被称为迪菲–赫尔曼密钥交换机制。这一机制以怀特菲德·<br/><br/>     迪菲(Whitfield Diffie)和马丁·赫尔曼(Martin Hellman)<br/><br/>     的名字命名,他们俩于1976年首次发表了这一算法。每次你访问<br/><br/>     一个安全网站(以“https:”而非“http:”开头)时,你的计<br/><br/>     算机和与其通信的网站服务器之间都会建立一个共享密钥,使用<br/><br/>     的方法是迪菲–赫尔曼机制或工作原理类似的替代方法之一。而<br/><br/>     一旦建立了共享密钥,这两台电脑就能使用之前描述的相加算法<br/><br/>     的变体对所有通信进行加密。图29 现实生活数字混合第四步:只有你和阿诺德能得到共享密钥数字,即通过<br/><br/>     使用幂和钟算计算将如箭头所示的元素组合起来<br/><br/>     还有很重要的一点值得注意,当迪菲–赫尔曼机制在现实中<br/><br/>     运用时,实际涉及的数字要远比我们在例子中使用的数字大。我<br/><br/>     们使用的钟大小很小(11),因此计算起来就很简单。但如果你<br/><br/>     选择的公开钟大小很小,那么可能的私人数字也会很小(因为你<br/><br/>     只能使用比钟大小小的私人数字)。而这也意味着有人可以使用<br/><br/>     计算机试出所有可能的私人数字,直到找到一个数字生成你的公<br/><br/>     开–私人数字。在上面的例子中,只有11个可能的私人数字,因<br/><br/>     此这个系统非常轻易就能被破解。相反,迪菲–赫尔曼机制在现<br/><br/>     实中运用时通常会使用几百个数位长的钟大小,这让可能的私人数字多得不可想象(比一万亿的一万亿次方还多得多)。即便如<br/><br/>     此,我们也需要小心地选取公开数字,以确保它们具有正确的数<br/><br/>     学性质——如果你感兴趣的话,请看下页的文字框。<br/><br/>     本章描述的迪菲–赫尔曼方法只是通过(电子)明信片通信<br/><br/>     的多种绝妙技巧之一。计算机科学家们称迪菲–赫尔曼方法为密<br/><br/>     钥交换算法(Key Exchange Algorithm)。其他公钥算法的运作<br/><br/>     方式不同,这能让你使用接收方宣布的公开信息,直接向潜在的<br/><br/>     接收方加密一条消息。相反,密钥交换算法能让你使用来自接收<br/><br/>     方的公开信息,建立一个共享密钥,但加密过程是通过加法把戏<br/><br/>     完成的。对互联网上绝大部分通信而言,后面的选项——我们在<br/><br/>     本章中了解到的这种方法——要更容易让人接受,因为它需要的<br/><br/>     计算能力小得多。<br/><br/>     但也有一些程序需要用到完整的公钥加密。这类程序中最有<br/><br/>     趣的可能要算数字签名了,我们将在第八章谈到它。你在阅读第<br/><br/>     八章时会发现,完整版公钥加密的思想类似于我们已经了解到<br/><br/>     的:机密信息和公开信息用一种在数学上不可逆的方式“混<br/><br/>     合”在一起,就像混合在一起的颜料一样,再也分不开。最著名<br/><br/>     的公钥加密系统是RSA,这个名字由首次发表该系统的三位发明<br/><br/>     者 姓 的 首 字 母 组 合 而 成 : 罗 纳 德 · 李 维 斯 特 ( Ronald<br/><br/>     Rivest)、阿迪·沙米尔(Adi Shamir)和雷奥纳德·阿德尔曼<br/><br/>     (Leonard M.Adlemen)。第八章用RSA作为解释数字签名如何运<br/><br/>     行的主要例子。<br/><br/>     迪菲–赫尔曼公开数字最重要的属性是,钟大小必须是<br/><br/>     一个素数——只有1和其自身两个除数。另一个有趣的要求是,基数必须是钟大小的本原根(primitive root)。这也<br/><br/>     意味着基数的幂最终将循环遍钟上每个可能的值。再看看前<br/><br/>     文提到的表,你会注意到2和6都是11的本原根,但3却不是<br/><br/>     ——3的幂循环的值有3、9、5、4和1,却没有2、6、7、8和<br/><br/>     10。<br/><br/>     在这些早期公钥算法发明的背后,都有一个迷人而复杂的故<br/><br/>     事。迪菲和赫尔曼的确是发表迪菲–赫尔曼机制的第一批人,时<br/><br/>     间是1976年。李维斯特、沙米尔和阿德尔曼也的确是发表RSA的<br/><br/>     第一批人,时间是1978年。但这并不是故事的全部!人们后来发<br/><br/>     现,英国政府在数年前就已经知道类似系统。不幸的是,那些发<br/><br/>     明迪菲–赫尔曼机制和RSA的先驱是英国政府通信实验室GCHQ的<br/><br/>     数学家。他们工作的结果被记录在内部机密文件中,直到1997年<br/><br/>     才被解密。<br/><br/>     RSA、迪菲–赫尔曼机制和其他公钥加密系统不仅仅是绝妙<br/><br/>     的思想,它们还发展成了商业技术和互联网标准,对商业和个人<br/><br/>     有着极其重要的意义。没有公钥加密,我们每天使用的绝大部分<br/><br/>     在线交易都不可能安全地完成。RSA的发明者在20世纪70年代为<br/><br/>     自己的系统申请了专利,而他们的专利直到2000年年末才失效。<br/><br/>     在专利失效的那天晚上,美国旧金山市的美国音乐大剧院举行了<br/><br/>     一场庆祝晚会——也许是为了庆祝公钥加密将永久为人们服务这<br/><br/>     一事实。<br/><br/>     [1] 对了解计算机数字系统的人而言,我在这里说的是小数位数,而非二进位<br/><br/>     数。对了解对数的人而言,将二进制数转化为小数位数的转换比例30%来自log10 2<br/><br/>     ≈ 0.3。第四章<br/><br/>     纠错码<br/><br/>     ——自纠正的错误告诉一个人他犯了错是一回事,让他掌握真理则是另一<br/><br/>     回事。<br/><br/>     ——约翰·洛克,《人类理智论》(Essay Concerning Human<br/><br/>     Understanding)<br/><br/>     如今,我们已习惯于在有需要时随时使用计算机。20世纪40<br/><br/>     年代在贝尔电话公司实验室工作的研究员理查德·汉明<br/><br/>     (Richard Hamming)就没这么幸运了:其他部门使用着他所需<br/><br/>     要的计算机,只有到周末时才能轮到他用。因此,你可以想象,由于计算机在读取自身数据时出错从而导致频繁崩溃后,他有多<br/><br/>     么沮丧。汉明在谈到这个问题时是这样说的:<br/><br/>     我要轮两周才能进去一次,却发现我所有的东西都被清<br/><br/>     空了,什么都没得到。我真的很生气,因为我想要这些答<br/><br/>     案,还浪费了我两个周末的时间。于是我说:“去他的,如<br/><br/>     果计算机能侦测到错误,为什么它不能对错误定位并进行纠<br/><br/>     正?”<br/><br/>     要说明发明纠错码的必要性,还有另外几个很鲜明的例子。<br/><br/>     汉明很快就创造了第一批纠错码:一种近乎神奇的能侦测并纠正<br/><br/>     计算机数据中错误的算法。没有纠错码,我们的计算机和通信系<br/><br/>     统就会比现在慢很多,功能弱许多,可靠性也会差很多。错误侦测及纠正的需求<br/><br/>     计算机有三项基本工作。最重要的工作是执行计算,即输入<br/><br/>     一些数据。计算机必须用某种方法转化数据,并得出一个有用的<br/><br/>     答案。但如果没有计算机执行的另外两项非常重要的工作——存<br/><br/>     储数据和传输数据,计算答案的能力基本上也没用。(计算机通<br/><br/>     常在内存和磁盘驱动器上存储数据,并且基本上通过互联网传输<br/><br/>     数据。)要深入理解这一点,想象一台既不能存储又不能传输信<br/><br/>     息的计算机,这样的计算机自然不会有什么用。的确,你可以做<br/><br/>     一些复杂计算(比如,准备一份复杂的财务报表,详细说明公司<br/><br/>     预算),但你不能将结果发送给同事,甚至不能保存结果以便返<br/><br/>     回继续操作。因此,传输和存储数据对现代计算机来说至关重<br/><br/>     要。<br/><br/>     图像<br/><br/>     但传输和存储数据要面临一个巨大的挑战:数据必须丝毫无<br/><br/>     差——因为在许多情况下,哪怕一丁点儿错误也会让数据变得毫<br/><br/>     无用处。作为人,我们也熟悉在不出错的情况下存储和传输信息<br/><br/>     的需求。比如,如果你写下某人的电话号码,按正确的顺序无误<br/><br/>     地记录下每位数至关重要。哪怕其中有一位数出错,那个电话号<br/><br/>     码对你或其他人都将毫无用处。在一些情况中,数据出错的后果<br/><br/>     要比毫无用处更糟。比如,在存储计算机软件的文件中有一个错<br/><br/>     误,就会导致程序崩溃或让程序做一些原本不应该做的事。(程<br/><br/>     序甚至可能会删除一些重要文件,或在你保存工作前崩溃。)而<br/><br/>     在一些计算机化的金融记录中出错,可能会导致实际的金钱损<br/><br/>     后的思想。结果证明,如果你运用正确的把戏,即便是极端不可<br/><br/>     一的错误率呢?本章将揭示让这一奇迹发生的绝妙计算机科学背<br/><br/>     取。面临如此显然的通信错误,我们怎么能希望实现数十亿分之<br/><br/>     媒体会由于灰尘或其他物理干扰的影响,被划伤、受损或不能读<br/><br/>     波动影响;无线通信无时无刻不受干扰;硬盘、CD和DVD等物理<br/><br/>     声。但电话并不是遭遇这类情况的唯一设备:电线受所有种类的<br/><br/>     息,因为电话对话经常要遭遇失真、静电噪声或其他类型的噪<br/><br/>     处理通信问题。电话就是个好例子:显然电话不能完美地传输信<br/><br/>     情况下,不犯任何一个错误。但和其他设备一样,计算机也必须<br/><br/>     也还是不够好。计算机必须能在存储和传输数十亿“块”信息的<br/><br/>     这个故事的教训是,对计算机而言,精确度达到99.999 9%<br/><br/>     的后果。<br/><br/>     错误——在你不曾预料到的情况下,每个错误都有可能导致崩溃<br/><br/>     每接收100万个字符就会出错一次,下载的软件中也会有逾20个<br/><br/>     况也适用于传输数据:如果你下载一个20兆的软件,你的计算机<br/><br/>     个错误,在设备容量被填满时(平均)也会有15个错误。这一情<br/><br/>     于1 500万页文本。因此,即便计算机存储系统每100万页会犯一<br/><br/>     写作本书时,这是低价笔记本电脑的标准容量。)这100 GB相当<br/><br/>     想下列情形。假设你有一个存储容量是100 GB的计算设备。(在<br/><br/>     储和传输的信息量绝对是海量。为了让你对信息量级有概念,想<br/><br/>     下,通过仔细检查来避免错误也不是太难。而计算机要无误地存<br/><br/>     信息——如银行账号、密码、电子邮件地址等——很重要的情况<br/><br/>     不过,人们需要存储的无误信息相对较少,而且在知道一些<br/><br/>     实际价格是每股8.34美元。)<br/><br/>     失。(假如你以为自己在买每股5.34美元的股票,而这只股票的靠的通信频道也可以以极低的错误率传输数据。而且这个错误率<br/><br/>     是如此之低,以至于在实际运作当中,错误几乎可以忽略不计。<br/><br/>     重复把戏<br/><br/>     要通过一个不可靠的频道进行可靠的通信,其中最根本的把<br/><br/>     戏是我们都熟悉的:要确保一些信息被正确地传输,你只需重复<br/><br/>     几次该信息。如果某人在电话连接很糟糕的情况下,念给你听一<br/><br/>     个电话号码或银行账号,你极有可能会要求对方至少重复一次,以便确认号码无误。<br/><br/>     计算机也能做同样的事情。假设银行的一台计算机试图通过<br/><br/>     互联网把你的账户余额传给你。你的账户余额是5 213.75美元,但不幸的是,网络不稳定,每个数字都有20%的概率变成其他数<br/><br/>     字。因此,当你的账户余额第一次被传输过来时,显示的可能是<br/><br/>     5 293.75美元。很显然,你没办法知道余额是否正确。所有的数<br/><br/>     字都有可能正确,但其中至少有一个数字可能出错,而你没有办<br/><br/>     法分辨是哪个出了错。但通过运用重复把戏(the repetition<br/><br/>     Trick),你就能很好地推测出真正的余额。假设你请求传出余<br/><br/>     额5次,并收到了以下反馈:注意,其中一些传输不止一位数出错,也有一次传输(传输<br/><br/>     2)没有出现错误。关键点在于,你没办法知道哪儿有错,因此<br/><br/>     也没办法将传输2挑选为正确的传输。相反,你可以做的事情就<br/><br/>     是单独检查每个数字,寻找同一数字的所有传输,然后选出出现<br/><br/>     最频繁的那个值。下面列出了所有传输项,最末尾是出现频率最<br/><br/>     高的数字:<br/><br/>     要把这个概念完全弄清楚,我们就需要看些例子。检查传输<br/><br/>     中的第一位数,在传输1~4中,第一位数都是“5”,而传输5的第一位数是“7”。换句话说,第一位数在4次传输中是“5”,而只在一次传输中是“7”。因此,尽管你不能完全肯定,但你<br/><br/>     银行余额第一位数的值最有可能是“5”。转到第二位数,我们<br/><br/>     看到“2”出现了4次,而“4”出现了1次,因此“2”最有可能<br/><br/>     是第二位数。第三位数有点儿有趣,因为有三种可能<br/><br/>     性:“1”出现了3次,“9”出现了1次,“4”出现了1次。但同<br/><br/>     样的原则也适用,“1”最有可能是真的值。通过对所有数字使<br/><br/>     用这种方法,你可以得到完整银行余额的最终推测:5 213.75美<br/><br/>     元,而这也正是正确的值。<br/><br/>     这种方法很简单。我们已经解决这个问题了吗?在某种程度<br/><br/>     上,是的。但你也许会对两件事感到不满。首先,这条信道的错<br/><br/>     误率只有20%,而在一些情况中,计算机需要在错误率远高于20%<br/><br/>     的信道中通信。其次,也许要更严肃些,上面例子的最终答案恰<br/><br/>     好是正确的,但它不能保证答案会永远都正确:它只是一个推<br/><br/>     测,基于我们的看法——认为它才最有可能是真的银行余额。幸<br/><br/>     运的是,这两件事都很容易处理:我们只需增加重新传输的次<br/><br/>     数,直到可靠性高到让我们满意为止。<br/><br/>     比如,假设最后一个例子中的错误率是50%而不是20%。你可<br/><br/>     以要求银行传输1 000次余额,而不是5次。让我们集中关注第一<br/><br/>     位数,因为其他数的工作原理都一样。由于错误率是50%,大约<br/><br/>     有一半的数会被正确地传输为“5”,但另一半会变成其他随机<br/><br/>     值。因此“5”会出现约500次,其他每个数(0~4和6~9)都会出<br/><br/>     现50次左右。数学家们能计算出某个数出现的次数比“5”多的<br/><br/>     概率:即便使用这个方法每秒传输一个新的银行余额,我们也得<br/><br/>     等上数万亿年才能猜错银行余额。这个故事的重点在于,通过重复一条不可靠的消息足够多次,你就可以让消息的可靠性高到让<br/><br/>     你满意为止。(在这些例子中,我们假设错误随机发生。相反,如果一个恶意实体故意干扰传输,并选择制造某些错误,重复把<br/><br/>     戏都会变得不可靠。后面介绍的一些代码在对抗这类恶意攻击时<br/><br/>     都表现良好。)<br/><br/>     因此,通过使用重复把戏,不可靠通信的问题能够被解决,错误基本上能被消灭。不幸的是,重复把戏对现代计算机系统来<br/><br/>     说还不够好。当传输像银行余额这样的“小块”数据时,重新传<br/><br/>     输1 000次耗费并不多,但在下载一个大型软件(假设有200兆)<br/><br/>     时,显然传输1 000份该软件完全不现实。很明显,计算机需要<br/><br/>     使用一些比重复把戏更成熟的方法。<br/><br/>     冗余把戏<br/><br/>     即便计算机不使用上面描述到的重复把戏,我们也在本章一<br/><br/>     开始就介绍它,以便让我们了解实际生活当中可靠通信最基本的<br/><br/>     原则。这条基本原则是,你不能只发送原始消息,你要发送一些<br/><br/>     多余的东西以增加可靠性。在重复把戏的例子中,你发送的额外<br/><br/>     东西就是更多份原始消息。但实际情况是,要提高可靠性,你还<br/><br/>     有其他许多多余的东西可以发送。计算机科学家们称这些多余的<br/><br/>     东西为“冗余”。有时候,冗余被附加在原始消息上。在研究下<br/><br/>     一个把戏(校验和把戏)时,我们会看到这种“附加”技术。但<br/><br/>     首先,我们要研究另一种添加冗余的方法。这种方法实际上是把<br/><br/>     原始消息转换成一条更长的冗余消息——原始消息会被删除,取<br/><br/>     而代之的是一条更长的不同消息。当收到更长的消息时,你就能将其转换回原始消息,即便这条冗余消息在糟糕的信道中传输时<br/><br/>     被破坏了。我们将这种方法简单地称为冗余把戏。<br/><br/>     举个例子更容易说清。之前我们尝试将你的银行余额5<br/><br/>     213.75美元通过一条不可靠的信道传输,这条信道有20%的概率<br/><br/>     随机替换数字。和尝试只传输“5 213.75”不同的是,让我们把<br/><br/>     这个数字转换成一条包含相同信息的更长的(因此也是“冗余<br/><br/>     的”)消息。在这个例子中,我们用英语单词简单地把余额拼出<br/><br/>     来:<br/><br/>     five two one three point seven five<br/><br/>     我们再假设,由于信道糟糕,这条消息中约20%的字符会变<br/><br/>     成其他随机字符。这条消息最终可能变成:<br/><br/>     fiqe kwo one thrxp point sivpn fivq<br/><br/>     尽管读起来有点儿讨厌,但我认为,任何知道英语的人都能<br/><br/>     猜出,这条被破坏的消息代表真正的银行余额5 213.75(美<br/><br/>     元),这点你应该会赞同。<br/><br/>     关键在于,因为我们使用了一条冗余消息,所以对消息中的<br/><br/>     任何单个变化进行可靠侦测及纠正变得可行。如果我告诉你,字<br/><br/>     母“fiqe”代表英语中的一个数字,且只有一个字母被替换了,你绝对能肯定原始消息中的单词是“five”,因为除此以外再也<br/><br/>     没有英语数字能通过替换“fiqe”中一个字母产生了。与此形成<br/><br/>     鲜明对比的是,如果我告诉你,数字“367”代表了一个数,但其中一个数字被替换了,你就没办法知道原始数字是多少,因为<br/><br/>     这条消息中没有冗余。<br/><br/>     尽管我们还没弄清冗余究竟是如何工作的,但却已经知道它<br/><br/>     和让消息变长有关,消息的每一部分都应该符合某种已知模式。<br/><br/>     通过这种方法,任何变化都能首先被识别(因为并不符合已知模<br/><br/>     式),然后被纠正(通过改正错误使其符合模式)。计算机科学<br/><br/>     家称这些已知模式为“代码字”(code words)。在上面的例子<br/><br/>     中 , 代 码 字 就 是 用 英 语 写 的 数 字 ,如“one”(一)、“two”(二)、“three”(三)等。<br/><br/>     现在是时候解释冗余把戏(The Redundany Trick)的运作<br/><br/>     原理了。消息由“符号”——计算机科学家是这么称呼的——组<br/><br/>     成。在我们这个简单的例子中,符号是数字0~9(我们会忽略美<br/><br/>     元符号以及小数点,让事情变得更简单)。每个符号都被指定了<br/><br/>     一个代码字。在这个例子中,符号1被指定的代码字是“one”,2被指定的代码字是“two”,依此类推。<br/><br/>     要传输一条信息,你首先要找出每个符号,并将符号转译成<br/><br/>     对应的代码字。其次,你将转换的消息通过不可靠信道发送。当<br/><br/>     消息被接收时,你查看消息的每个部分,检查其是否为有效的代<br/><br/>     码字。如果它是有效的(如“five”),你只需将其转换为相应<br/><br/>     的 符 号 ( 如 “5” ) 即 可 。 如 果 不 是 有 效 的 代 码 字<br/><br/>     (如“fiqe”),你就要找出它和哪个代码字最匹配(在这个例<br/><br/>     子中就是“five”),并将那个无效代码字转换成相应的符号<br/><br/>     (也就是“5”)。使用这些代码的例子如下图所示:图30 使用英文单词表示数字的代码<br/><br/>     这就是全部过程。实际上,计算机在存储和传输信息时会一<br/><br/>     直用到这个冗余把戏。和我们在例子中使用的英语相比,数学家<br/><br/>     们已经找到了更漂亮的代码字,但可靠计算机通信的工作原理仍<br/><br/>     然相同。下页的图就列举了一个真实例子。这个例子被计算机科<br/><br/>     学家们称为(7,4)汉明代码(Hamming code),这是理查德·<br/><br/>     汉明于1947年在贝尔实验室发明的代码之一,就是为了处理之前<br/><br/>     说过的周末计算机崩溃的情况。(由于贝尔实验室的要求,汉明<br/><br/>     申请了这些代码的专利,直到3年后的1950年才发表。)和我们<br/><br/>     在前面用到的代码相比,汉明代码最明显的区别是所有事情都通<br/><br/>     过0和1完成。因为计算机存储和传输的每一“块”数据都会被转<br/><br/>     化为0和1的字符串,现实生活中使用的所有代码也限用这两个数<br/><br/>     字。图31 计算机使用的真实代码。计算机科学家们称这一代码为(7, 4)汉明代<br/><br/>     码。注意,“编码”框中只列出了16个可能的四位数输入中的5个。其余的输入也都<br/><br/>     有相应的代码字,但它们在这里被省略了<br/><br/>     除此以外,所有事情都和前面一模一样。在编码时,每一组<br/><br/>     4位数字都加入了冗余,由此产生了一个7位数的代码字。在解码<br/><br/>     时,你首先要为接收的7位数寻找完全匹配,如果寻找完全匹配<br/><br/>     失败,就选择最接近的匹配。你也许会担心,现在我们在和0及1<br/><br/>     打交道,也许相近的匹配不止一个,最后可能会选择错误的解<br/><br/>     码。不过,这种特殊代码的设计非常精巧,7位数代码字中的任<br/><br/>     何错误都能得到确定无疑的纠正。在设计带有这种属性的代码背<br/><br/>     后是一些美丽的数学原理,但在这里,我们不会深究其细节。<br/><br/>     值得强调的是,为什么冗余把戏在实际应用中要比重复把戏<br/><br/>     更受欢迎。主要是这两个把戏的相对成本。计算机科学家们使<br/><br/>     用“杂项”(overhead)衡量纠错系统的成本。杂项就是为确保<br/><br/>     消息被正确接收而发送的多余信息。重复把戏的杂项数量巨大,因为你必须发送数份完整消息。冗余把戏的杂项取决于你使用的<br/><br/>     代码字的具体类型。上面的例子使用了英语作为代码字,冗余消<br/><br/>     息有35个字母长,而原始消息只含有6个数字,因此冗余把戏这<br/><br/>     一特殊应用的杂项也很大。但数学家们已经找到了冗余度低很多的代码字,而且它在查出错误的概率上效率惊人。这些代码字的<br/><br/>     低杂项也是计算机使用冗余把戏——而非重复把戏——的原因。<br/><br/>     到目前为止,我们进行的讨论都使用了利用代码传输信息的<br/><br/>     例子,但我们讨论过的所有事情都能很好地在存储信息的任务中<br/><br/>     应用。CD、DVD和计算机硬盘都极度依赖纠错码,以实现我们在<br/><br/>     现实中观察到的超级可靠性。<br/><br/>     校验和把戏<br/><br/>     目前为止,我们研究了同时侦测和纠正数据中错误的方法。<br/><br/>     重复把戏和冗余把戏都属于此类方法。但还有另外一种可能的方<br/><br/>     法能解决整个问题:我们可以先不管纠错,而是将精力集中在侦<br/><br/>     测错误上。(17世纪的哲学家约翰·洛克对错误侦测和错误纠正<br/><br/>     之间的区别有清楚的认识——正如你在本章开篇引言中所看到的<br/><br/>     那样。)对许多软件而言,只侦测到一个错误就足够了,因为如<br/><br/>     果你侦测到了一个错误,请求再发送一份数据即可。而且你可以<br/><br/>     一直请求新拷贝,直到得到完全无误的拷贝。这是最常使用的策<br/><br/>     略。几乎所有互联网连接都使用这一技术。我们称这一方法<br/><br/>     为“校验和把戏”(The Checksum Trick),这么命名的原因很<br/><br/>     快就会明朗。<br/><br/>     要理解校验和把戏,就要先假设我们所有的消息都只由数字<br/><br/>     组成会更方便些。这是一个非常真实的假设,因为计算机用数字<br/><br/>     存储所有的信息,只有在向人展示信息时,才把数字转译成文本<br/><br/>     或图像。不过,在本章所有的例子中,任何对消息符号的特殊选<br/><br/>     择都不影响本章描述的技术,理解这点很重要。有时候使用数字符号(0~9)更方便,而有时候使用字母符号(a~z)要更加方<br/><br/>     便。不过,不管是使用哪种符号,我们都能就这些符号之间的一<br/><br/>     些转译达成一致。比如,从字母转译为数字符号的一个明显例子<br/><br/>     就是a→01,b→02,……,z→26。因此,我们是在探究一项传<br/><br/>     输数字消息还是字母消息的技术就变得无关紧要了。通过首先对<br/><br/>     符号进行简单且固定的转译,这项技术稍后将被应用在任何种类<br/><br/>     的消息上。<br/><br/>     到这里,我们必须了解校验和究竟是什么。校验和的种类有<br/><br/>     很多,但目前我们将着重于最简单的那种校验和——我们称之<br/><br/>     为“简单校验和”(Simple Checksum)。计算一条数字消息的<br/><br/>     简单校验和的确很容易:你只需将消息中的所有数字相加,只保<br/><br/>     留结果的最后一位数,剩下的数字就是你的简单校验和。比如,假设消息是:<br/><br/>     4 6 7 5 6<br/><br/>     那么所有数字之和为4+6+7+5+6=28,但我们只保留最后一位<br/><br/>     数,因此这条消息的简单校验和是8。<br/><br/>     但如何使用校验和呢?很简单,你只需在发送原始消息前,将原始消息的校验和附加到消息末尾即可。别人在接收消息后,就能再计算校验和,并和你发送的校验和比较,看收到的消息是<br/><br/>     否 正 确 。 换 句 话 说 , 他 们 “check” ( 校 验 ) 消 息<br/><br/>     的“sum”(和)就是术语“checksum”(校验和)的由来。继<br/><br/>     续说上面的例子。消息“46756”的简单校验和是8,因此我们这<br/><br/>     样来传输消息及其校验和:4 6 7 5 6 8<br/><br/>     现在,接收消息的人必须知道你使用的是校验和把戏。假设<br/><br/>     他们确实知道,他们就能立即认出最后一位数8不属于原始消<br/><br/>     息,然后把最后一位数放到一边,再计算其他数的和。如果在传<br/><br/>     输这条消息时没有出现错误,他们会计算4+6+7+5+6=28,保留最<br/><br/>     后一位数(也就是8),再将最后一位数和之前放到一边的校验<br/><br/>     和比较,看是否相等(的确相等),因此得出结论,消息已被正<br/><br/>     确地传输。但如果传输消息时出错了,这时会发生什么?假设7<br/><br/>     随机变为3。那么你会收到如下消息:<br/><br/>     4 6 3 5 6 8<br/><br/>     你 将 8 放 到 一 边 以 备 后 续 比 较 , 并 计 算 校 验 和 为<br/><br/>     4+6+3+5+6=24,只保留最后一位数(4)。4和之前放到一边的8<br/><br/>     并不相等,因此你可以肯定消息在传输途中遭到了破坏。这时,你请求重新传输消息,直到接收新的拷贝,然后再次计算并比较<br/><br/>     校验和。你可以一直这么做,直到得到一条校验和正确的消息为<br/><br/>     止。<br/><br/>     所有这一切太过美好,似乎不可能成真。因为一个纠错系统<br/><br/>     的“杂项”就是在发送消息本身以外要发送的额外信息量。好<br/><br/>     吧,我们似乎得到了终极低杂项系统,因为不管消息有多长,我<br/><br/>     们只需多添加一位数(校验和)就能侦测错误!<br/><br/>     结果确实证明简单校验和系统太过美好,不能成真。简单校<br/><br/>     验和的问题是:上面描述到的简单校验和最多只能在消息中侦测<br/><br/>     出一处错误。如果有两个或更多错误,简单校验和或许能侦测到它们,但也有可能侦测不到。让我们来看看这个问题的一些例<br/><br/>     子:<br/><br/>     原始消息(46756)和前面一样,其校验和也没变(8)。下<br/><br/>     一行的消息有一个错误(第一个数是1而不是4),其校验和为<br/><br/>     5。事实上,你很有可能说服自己,更改任何单个数字都会导致<br/><br/>     与8不同的校验和,因此你保证能侦测到消息中的任何单个错<br/><br/>     误。要证明这一点永远为真并不难:如果只有一个错误,简单校<br/><br/>     验和绝对能保证侦测到它。<br/><br/>     再下一行,我们看到一条带有两处错误的消息:前两个数都<br/><br/>     被替换了。这条消息的校验和恰好是4。而由于4和原始校验和8<br/><br/>     不同,收到这条消息的人就能侦测到出现了一个错误。然而,我<br/><br/>     们在最后一行遇到了麻烦。这也是一条有两处错误的消息,也是<br/><br/>     前两位数出错。但出错的两位数的值不同,而且这条有两处错误<br/><br/>     的消息的校验和恰好也是8——和原始校验和一样!因此接收这<br/><br/>     条消息的人将不能侦测到消息中有错误。<br/><br/>     幸运的是,我们可以通过对校验和把戏进行一些微调来解决<br/><br/>     这个问题。第一步是定义一种新的校验和。让我们称这种新的校<br/><br/>     验和为“阶梯校验和”(Staircase Checksum),因为这个名字有助于通过想象在爬楼梯进行计算。想象你处于楼梯的底部,楼<br/><br/>     梯台阶编号为1、2、3……依此类推。要计算阶梯校验和,你就<br/><br/>     要像之前一样把数字相加,但每个数都要和该数字所在位阶数相<br/><br/>     乘,每个数都比前一个数大一个位阶。最后,你只保留最后一位<br/><br/>     数,和简单校验和一样。因此,假如消息是:<br/><br/>     4 6 7 5 6<br/><br/>     和之前类似,阶梯校验和通过首先计算阶梯和来计算:<br/><br/>     (1×4)+(2×6)+(3×7)+(4×5)+(5×6)<br/><br/>     =4+12+21+20+30<br/><br/>     =87<br/><br/>     然后只保留最后一位数,也就是7。因此“46756”的阶梯校<br/><br/>     验和为7。<br/><br/>     所有这一切想说明什么?如果你同时使用简单校验和及阶梯<br/><br/>     校验和,那么你就保证能侦测到任何消息中的两处错误。因此,用我们新的校验和把戏来传输原始消息会多出两个数字:首先是<br/><br/>     简单校验和,其次是阶梯校验和。比如,消息“46756”会以“4<br/><br/>     6 7 5 6 8 7”的形式被传输。当你收到消息时,你仍然必须提<br/><br/>     前知道会运用哪些把戏。但假设你确实知道,那么检查错误就像<br/><br/>     使用简单校验和一样容易。在这个例子中,你先把最后两个数<br/><br/>     (简单校验和8及阶梯校验和7)放到一边,然后计算消息其余部<br/><br/>     分的简单校验和(46756的简单校验和是8),也要计算阶梯校验和(结果为7)。如果两个校验和值和发送的两个校验和匹配<br/><br/>     (这个例子中的两个值的确匹配),你就可以保证这条消息要么<br/><br/>     是正确的,要么至少有三处错误。<br/><br/>     下一张表显示了这两种校验和的实际运用情况。这张表和前<br/><br/>     面那张表几乎一模一样,除了在每行末尾加上了阶梯校验和,以<br/><br/>     及新加了一行作为额外的例子。当消息中有一处错误时,我们会<br/><br/>     发现这条消息的简单校验和及阶梯校验和均与原始的消息不同<br/><br/>     (简单校验和是5而不是8,阶梯校验和是4而不是7)。当消息中<br/><br/>     有两处错误时,有可能两个校验和值都不相同,如表中第3行的<br/><br/>     简单校验和是4而不是8,阶梯校验和是2而不是7。但正如我们已<br/><br/>     经发现的,当消息中有两处错误时,该消息的简单校验和不会改<br/><br/>     变。表中第4行就是这种情况的一个例子,其简单校验和仍然是<br/><br/>     8。但因为阶梯校验和与原始消息不同(是9而不是7),我们仍<br/><br/>     然知道这条消息有误。在表中最后一行,我们能看到还有另外一<br/><br/>     种情况:这条含有两处错误的消息的简单校验和不同(是9而不<br/><br/>     是8),但其阶梯校验和却一样(7)。不过,这里的意思是我们<br/><br/>     仍然能侦测到错误,因为两个校验和中至少有一个和原始校验和<br/><br/>     不同。尽管需要用一些稍微有技术性的数学方式来证明,但有一<br/><br/>     点是确认无疑的:只要错误不超过两处,你就都能够侦测到错<br/><br/>     误。既然我们对基本方法有了初步了解,我们就需要意识到,刚<br/><br/>     刚描述的校验和把戏只能保证对相对较短的消息奏效(少于10位<br/><br/>     数)。但与此非常类似的概念能被应用在较长的消息上。通过一<br/><br/>     定的简单操作序列,如把数字加起来,将数字和其位阶相乘,或<br/><br/>     按照固定模式将一些数字交换,我们还是有可能定义校验和的。<br/><br/>     尽管这听起来很复杂,计算机却能毫不费力地迅速计算这些校验<br/><br/>     和。结果证明,这些方法用在侦测消息中的错误上极其有效且实<br/><br/>     用。<br/><br/>     上面描述的校验和把戏只生成了两个校验和数字(简单校验<br/><br/>     和及阶梯校验和),但真正的校验和通常会生成比这长得多的数<br/><br/>     字——有时长达150位。(我在本章中讲的都是十进制数0~9,而<br/><br/>     不是二进制数0和1,二进制数在计算机通信中会更经常被用<br/><br/>     到。)重点是,校验和的长度(要么和上面的例子一样是2位,要么和在实际中运用的校验和一样有近150位)是固定的。不<br/><br/>     过,尽管所有校验和算法生成的校验和长度都是固定的,只要你愿意,你都能计算消息的校验和。因此,对非常长的消息来说,即便是一个相对较大的校验和(如150位数),最终和消息本身<br/><br/>     相比也极小。比如,假设你从互联网上下载了一个20兆的软件<br/><br/>     包,你使用了一个100位数的校验和来验证它的正确性。软件包<br/><br/>     的校验和比不上软件包大小的十万之一。我敢肯定,你会认为这<br/><br/>     个杂项水平可以接受!而数学家会告诉你,使用这种长度的校验<br/><br/>     和侦测错误,其失败的概率极其微小,在现实中几乎不可能失<br/><br/>     败。<br/><br/>     和前面一样,这里也有几处重要的技术细节。并不是任何一<br/><br/>     个百位数校验和系统对失败都有如此高的抵抗性。这需要一种被<br/><br/>     计 算 机 科 学 家 称 为 加 密 哈 希 函 数 ( Cryptographic Hash<br/><br/>     Function)的特定校验和,尤其是在恶意敌人而非糟糕信道的随<br/><br/>     机变动对信息做出改变时。这是个非常现实的问题,因为也许就<br/><br/>     有一名邪恶“黑客”试图更改这个20兆大小的软件包,并让其具<br/><br/>     有相同的100位校验和数,而这个不同的软件其实是要控制你的<br/><br/>     计算机!使用加密哈希函数能消除这种可能性。<br/><br/>     定位把戏<br/><br/>     既然知道了校验和,现在我们就可以回到最初同时侦测和纠<br/><br/>     正通信错误的问题了。我们已经知道如何做到这一点:要么使用<br/><br/>     低效的重复把戏,要么使用高效的冗余把戏。但还是让我们先回<br/><br/>     到这个问题,因为我们从未真正地了解代码字是如何被创制的,而代码字则是这些把戏的关键。我们的确有用英语单词描述数字<br/><br/>     的例子,但那种代码字不如计算机实际使用的代码字高效;我们也看过一段汉明代码的真实例子,但它没有解释代码字一开始是<br/><br/>     如何生成的。<br/><br/>     因此,现在我们要学习另一套可能的代码字,用来执行冗余<br/><br/>     把戏。因为这种冗余把戏很特别,它能让你迅速定位一处错误,我们称其为“定位把戏”(The Pinpoint Trick)。<br/><br/>     正如我们在校验和把戏中做的一样,我们将和完全由数字<br/><br/>     0~9组成的消息打交道,但你要记住,这只是为了方便起见。将<br/><br/>     字母消息转译成数字很简单,因此在这里描述的技术能被应用到<br/><br/>     任何消息上。<br/><br/>     为简单起见,让我们假设消息恰好有16个数字,但这并非该<br/><br/>     技术在现实中的应用。如果你有一条长消息,就将其打碎成16位<br/><br/>     数长的“块”,并单独处理每“块”数据。如果消息比16个数字<br/><br/>     短,就用0把它补成16位数。<br/><br/>     定位把戏的第一步是重新排列消息中的16个数,将其排列成<br/><br/>     一个从左往右、自上向下读的方框。如果实际消息是:<br/><br/>     4 8 3 7 5 4 3 6 2 2 5 6 3 9 9 7<br/><br/>     就重新排列为:下一步,我们将计算每一行的校验和,并添加在每行的右<br/><br/>     侧:<br/><br/>     这些简单校验和的计算方式和前面一样。比如,要得到第二<br/><br/>     行的校验和,你就需要计算5+4+3+6=18,并保留最后一位数8。<br/><br/>     定位把戏的下一步是计算每一栏的简单校验和,并将其添加<br/><br/>     在每列的底部:和前面一样,求简单校验和的方法很清楚。比如,要得到第<br/><br/>     二行的校验和,你就需要计算3+3+5+9=20,并保留最后一位数<br/><br/>     0。<br/><br/>     定位把戏的下一步是重新排列所有数,让其能以一次一个数<br/><br/>     的方式被存储或传输。你通过从左往右、自上向下的方式读数。<br/><br/>     因此,最后你会得到如下24位数的消息:<br/><br/>     4 8 3 7 2 5 4 3 6 8 2 2 5 6 5 3 9 9 7 8 4 3 0 6<br/><br/>     现在,想象你已经收到了一条使用定位把戏传输的消息。你<br/><br/>     需要采取哪些步骤来得到原始消息,纠正其中出现的任何通信错<br/><br/>     误?让我们举个例子来说明。原始的16位数消息和上面的一样,但为了让事情变得更有趣,我们假设出现了一处通信错误——其<br/><br/>     中一个数被替换了。现在还不必担心被替换的数是哪个,我们很<br/><br/>     快就能运用定位把戏来确定。<br/><br/>     假设你收到的24位数的消息是:<br/><br/>     4 8 3 7 2 5 4 3 6 8 2 7 5 6 5 3 9 9 7 8 4 3 0 6你要做的第一步就是把数字放入一个5×5的方框中,最后一<br/><br/>     行和最后一列都对应随原始消息一起被发送的校验和数字:<br/><br/>     接下来,计算每一行、每一列四个数的简单校验和,在接收<br/><br/>     的校验和值旁边新建一行和一列,并在其中记录计算结果:<br/><br/>     这里会出现两组校验和值:你发送的,以及你计算出来的,记住这一点至关重要。在绝大多数情况下,两套值都一样。事实<br/><br/>     上,如果它们都一样,你就可以得出结论,收到的消息极有可能<br/><br/>     是正确的。但如果出现一处通信错误,计算得出的一些校验和值<br/><br/>     就会和发送的不同。注意,这个例子中有两个不同之处:第三行的5和0不同,第二列的3和8不同。冲突的校验和在框中被标注了<br/><br/>     出来:<br/><br/>     关键在于:这些不同之处的位置正好说明了通信错误出现的<br/><br/>     位置。错误肯定是在第三行(因为其他行的校验和都正确),错<br/><br/>     误也肯定是出现在第二列(因为其他列的校验和都正确)。正如<br/><br/>     你能在下面看到的,这将错误的可能性圈定为一种——框中标出<br/><br/>     的7:但这还不是全部,我们定位了错误,但还没纠正它。幸运的<br/><br/>     是,我们很容易就能做到这一点:我们只要用一个能让两个校验<br/><br/>     和都正确的数字替换出错的7即可。我们能看出,第二栏的校验<br/><br/>     和本应为3,但结果是8。换句话说,校验和需要减5。我们把错<br/><br/>     误的7减5,就能得到2:<br/><br/>     你甚至可以通过检查第三行来验证这一改变。第三行的校验<br/><br/>     值现在变成了5,和收到的校验和一致。错误同时被定位和纠正<br/><br/>     了。最后一步很明显,就是将纠正后的原始16位数消息从5×5的<br/><br/>     框中取出,方法是从左往右、自上向下(当然要忽略最后一行和<br/><br/>     最后一列)。结果是:<br/><br/>     4 8 3 7 5 4 3 6 2 2 5 6 3 9 9 7<br/><br/>     这和我们一开始用到的消息相同。<br/><br/>     在计算机科学中,定位把戏的名称是“二维奇偶校验<br/><br/>     码”(Two-Dimensional Parity)。奇偶校验码这个词和简单校验和的意思一样,计算机在处理二进制数字时经常用到它。而奇<br/><br/>     偶校验码被形容为二维,是因为消息被放在有两个维度的表格<br/><br/>     (行和列)中。二维奇偶校验码在一些真正的计算机系统中也有<br/><br/>     运用,但并不如其他一些冗余把戏高效。我在这里解释它的原因<br/><br/>     是,它能很容易地具化并展现在不要求复杂数学的情况下,于当<br/><br/>     今计算机系统中的流行代码背后发现并纠正错误。<br/><br/>     现实世界中的纠错及侦错<br/><br/>     纠错码于20世纪90年代问世,距离电子计算机诞生不久。回<br/><br/>     顾一下不难看出原因:早期计算机相当不可靠,组件经常出现错<br/><br/>     误。但纠错码的真正根源出现得还要早,是在电报和电话等通信<br/><br/>     系统中出现的。因此,这两大导致纠错码发生的事件都发生在贝<br/><br/>     尔电话公司的研究实验室中也就不奇怪了。我们故事中的两位英<br/><br/>     雄——克劳德·香农(Claude Shannon)和理查德·汉明——都<br/><br/>     是贝尔实验室的研究人员。前面已经介绍了汉明:正是他对公司<br/><br/>     的计算机在周末崩溃的愤怒,直接导致了第一批纠错码的发明,也就是现在闻名的汉明代码。<br/><br/>     不过,纠错码只是一个更大专业的一部分,这个专业被称为<br/><br/>     信息理论学(Information Theory),而绝大多数计算机科学家<br/><br/>     将信息理论学的诞生归因于克劳德·香农在1948年发表的一篇论<br/><br/>     文。香农的一本自传中将这篇名为《通信的数学理论》(The<br/><br/>     Mathematical Theory of Communication)的卓越论文形容<br/><br/>     为“信息时代的大宪章”。欧文·里德(Irving Reed)则这么<br/><br/>     形容这篇论文:“20世纪只有几件事能在对科学和工程学的影响力上超越(这篇论文)。通过这篇里程碑式的论文……他极大地<br/><br/>     改变了通信理论和实践的所有方面。”欧文·里德是里德–香农<br/><br/>     代码的共同发明人,我们将在下面提到里德–香农代码。为什么<br/><br/>     赞誉如此之高?香农通过数学展示了有可能从根本上通过一个嘈<br/><br/>     杂的、引发错误的链接实现错误率极低的通信。直到数十年后,科学家们才在现实中接近了香农理论的最大通信率。<br/><br/>     顺便说一下,香农的兴趣非常广泛。作为1956年达特茅斯人<br/><br/>     工智能大会(将在第五章末谈到)的四位主要组织者之一,他积<br/><br/>     极参与了另一领域的创立:人工智能。这还不够。他还骑单轮<br/><br/>     车,并制造了一辆令人难以置信的单轮车。这辆单轮车有一个椭<br/><br/>     圆轮子,意味着车手随着单轮车前进可以上下移动!<br/><br/>     香农的工作将汉明代码放到了一个更大的理论环境中,它为<br/><br/>     许多层面的深入发展打下了基础。自此以后,汉明代码被用于最<br/><br/>     早期的一些计算机中,并仍广泛用于一些特定种类的内存系统<br/><br/>     中。里德–所罗门(Reed-Solomon)代码是另一类重要代码。这<br/><br/>     种代码能被用来纠正每个代码字中的众多错误。[与(7, 4)汉<br/><br/>     明代码截然不同,汉明代码只能纠正7位数代码字中的一个错<br/><br/>     误。]里德–所罗门代码基于一个名为有限域代数(Finite<br/><br/>     Field Algebra)的数学分支,但你可以非常粗略地想象,它结<br/><br/>     合了阶梯校验和及二维定位把戏的特色。CD、DVD和计算机硬盘<br/><br/>     中都用到了里德–所罗门代码。<br/><br/>     校验和在现实中的运用也很广泛,它一般用于侦测而非纠正<br/><br/>     错误。也许最常见的例子就是以太网了,现今世界上几乎所有计<br/><br/>     算机都用这一联网协议。以太网中应用了一种被称为CRC-32的校<br/><br/>     验和来侦测错误。最为普遍的互联网协议TCP也在其发送的每“块”(或包)数据上使用校验和。校验和不正确的包直接被<br/><br/>     丢弃了,因为TCP的设计原则就是在以后必要时自动传输这些<br/><br/>     包。发布在互联网上的软件包通常使用校验和验证:其中一种流<br/><br/>     行的校验和是MD5,另一种是SHA-1。这两种校验和都属于加密哈<br/><br/>     希函数——为抵御恶意篡改软件提供保护,也能防止随机通信错<br/><br/>     误的出现。MD5校验和约有40位数长,SHA-1生成的数约有50位。<br/><br/>     SHA-1的同类校验和中有些抗错性甚至要更好,如SHA-256(约75<br/><br/>     位数)和SHA-512(约150位数)。<br/><br/>     纠错及侦测代码这门科学在不断地壮大。自20世纪90年代开<br/><br/>     始,一种名为低密度奇偶校验码(Low-Density Parity-check<br/><br/>     Codes)的方法受到了极大关注。这些代码如今的用途非常广<br/><br/>     泛,从卫星电视到通过深海光线进行的通信。下次你在周末观看<br/><br/>     高清卫星电视节目时,不妨遐思一下这个令人回味的反讽:正是<br/><br/>     由于理查德·汉明在周末与早期计算机斗争时产生了困扰,才有<br/><br/>     了我们现在周末的娱乐。第五章<br/><br/>     图形识别<br/><br/>     ——从经验中学习分析引擎没有原创任何东西的权利。它只能执行我们的<br/><br/>     指令。<br/><br/>     ——艾达·勒芙蕾丝,摘自她1843年有关分析引擎的笔记<br/><br/>     在前面各章提到的我们探索过的领域里,计算机的能力都要<br/><br/>     远超人的能力。比如,计算机通常可以在一两秒内加密或解密一<br/><br/>     个大文件,而人通过手动计算执行相同的任务则需要数年时间。<br/><br/>     举个更极端的例子,假设让人根据第二章中描述的算法手动计算<br/><br/>     数十亿网页的PageRank权重。这项任务太大,我们在现实中不可<br/><br/>     能完成这项任务。但互联网搜索公司的计算机在持续不断地执行<br/><br/>     这些计算。<br/><br/>     在本章,我们将审视人类具有天然优势的一个领域:图形识<br/><br/>     别领域。图形识别是人工智能的一部分,它包括面部识别、物体<br/><br/>     识别、语音识别和笔迹识别等任务。更具体的例子如判定一张照<br/><br/>     片是不是你姊妹的照片,或判定手写信封上的城市及州名。因<br/><br/>     此,图形识别可以被更通俗地定义为,让计算机基于输入数据开<br/><br/>     展“聪明的”行动的任务,这些数据包含大量的变量。<br/><br/>     给“聪明的”加双引号的理由很充分:计算机是否能展现出<br/><br/>     真正的智能,这个问题具有高度争议性。本章的开篇引言代表了<br/><br/>     这一争论中最早的论述之一:艾达·勒芙蕾丝于1843年就一台早<br/><br/>     期机械计算机的设计发表评论,这台早期计算机被称为分析引擎<br/><br/>     (Analytical Engine)。但在这一声明中,她着重说明了计算机缺乏原创性:它们必须严格遵循人类程序员的指令。一段时间<br/><br/>     以来,计算机科学家们就计算机能否从根本上展现智能争论不<br/><br/>     休。而如果把哲学家、神经科学家和神学家也算上的话,这一争<br/><br/>     论甚至会变得更复杂。<br/><br/>     幸运的是,我们不必在本章解决机器智能的悖论。从我们的<br/><br/>     目的出发,我们最好还是将“智能”这个词换成“有用”。因<br/><br/>     此,图形识别的基本任务就是处理一些变量极多的数据——如不<br/><br/>     同光照环境下的各种人脸照片,或不同人书写许多不同字的笔迹<br/><br/>     样本——并做一些有用的事。毫无疑问,人能够智能地处理这些 ......</div> <!--DuYiHuaAdd EndContent--></div> <div id="txtThisUrl"><br/>    <a href="http://www.100md.com/html/file/202004/164677.htm" target="_blank">http://www.100md.com/html/file/202004/164677.htm</a></div> <div id="txttips"><br/>您现在查看是摘要介绍页,<a href="http://www.100md.com/about/help.htm"> 详见PDF附件(7918KB,302页)</a>。</div> <script language="javascript" type="text/javascript" src="http://www.100md.com/comm/v2019/login.js"></script> <script language="javascript" type="text/javascript" src="http://www.100md.com/comm/v2019/after.js"></script> <div id="theRInfo"><script language="javascript" type="text/javascript" src="http://www.100md.com/rjs/file/202004/164677.js"></script><script language="javascript" type="text/javascript" src="http://www.100md.com/comm/v2019/related.js"></script></div> </div><div id="right"><script language="javascript" type="text/javascript" src="http://www.100md.com/comm/v2019/right.js"></script></div> </div><div id="copyright"><script language="javascript" type="text/javascript" src="http://www.100md.com/comm/v2019/copyright.js"></script></div></body></html>