王垠:数学和编程

好些人来信问我,要成为一个好的程序员,数学基础要达到什么样的程度?十八年前,当我成为大学计算机系新生的时候,也为同样的问题所困扰。面对学数学,物理等学科的同学,我感到自卑。经常有人说那些专业的知识更加精华一些,难度更高一些,那些专业的人毕业之后如果做编程工作,水平其实比计算机系毕业的还要高。直到几年前深入研究程序语言之后,对这个问题我才得到了答案和解脱。由于好多编程新手遇到同样的困扰,所以我想在这里把这个问题详细的阐述一下。

数学并不是计算机科学的基础

很多人都盲目的认为,计算机科学是数学的一个分支,数学是计算机科学的基础,数学是更加博大精深的科学。这些人以为只要学会了数学,编程的事情全都不在话下,然而事实却并非如此。

事实其实是这样的:

  • 计算机科学其实根本不是数学,它只不过借用了非常少,非常基础的数学,比高中数学还要容易一点。所谓“高等数学”,在计算机科学里面基本用不上。
  • 计算机是比数学更加基础的工具,就像纸和笔一样。计算机可以用来解决数学的问题,也可以用来解决不是数学的问题,比如工程的问题,艺术的问题,经济的问题,社会的问题等等。
  • 计算机科学是完全独立的学科。学习了数学和物理,并不能代替对计算机科学的学习。你必须针对计算机科学进行学习,才有可能成为好的程序员。
  • 数学家所用的语言,比起常见的程序语言(比如C++,Java)来说,其实是非常落后而糟糕的设计。所谓“数学的美感”,其实大部分是夜郎自大。
  • 99%的数学家都写不出像样的代码。

数学是异常糟糕的语言

这并不是危言耸听。如果你深入研究过程序语言的理论,就会发现其实数学家们使用的那些符号,只不过是一种非常糟糕的程序语言。数学的理论很多是有用的,然而数学家门用于描述这些理论所用的语言,却是纷繁复杂,缺乏一致性,可组合性(composability),简单性,可用性。这也就是为什么大部分人看到数学就头痛。这不是他们不够聪明,而是数学语言的“设计”有问题。人们学习数学的时候,其实只有少部分时间在思考它的精髓,而大部分时间是在折腾它的语法。

举一个非常简单的例子。如果你说cos2θ表示(cos θ)2,那么理所当然,cos-1θ就应该表示1/(cos θ)了?可它偏偏不是!别被数学老师们的教条和借口欺骗啦,他们总是告诉你:“你应该记住这些!” 可是你想过吗:“凭什么?” cos2θ表示(cos θ)2,而cos-1θ,明明是一模一样的形式,表示的却是arccos θ。一个是求幂,一个是调用反函数,风马不及,却写成一个样子。这样的语言设计混淆不堪,却喜欢以“约定俗成”作为借口。

如果你再多看一些数学书,就会发现这只是数学语言几百年累积下来的糟粕的冰山一角。数学书里尽是各种上标下标,带括号的上标下标,x,y,z,a,b,c,f,g,h,各种扭来扭去的希腊字母,希伯来字母…… 斜体,黑体,花体,双影体,……用不同的字体来表示不同的“类型”。很多符号的含义,在不同的子领域里面都不一样。有些人上一门数学课,到最后还没明白那些符号是什么意思。

直到今天,数学家们写书仍然非常不严谨。他们常犯的一个错误是把x2这样的东西叫做“函数”(function)。其实x2根本不是一个函数,它只是一个表达式。你必须同时指明“x是参数”,加上x2,才会成为一个函数。所以正确的函数写法其实看起来像这样:f(x) = x2。或者如果你不想给它一个名字,可以借用lambda calculus的写法,写成:λx.x2

可是数学家们灰常的喜欢“约定俗成”。他们定了一些不成文的规矩是这样:凡是叫“x”的,都是函数的参数,凡是叫“y”的,都可能是一个函数…… 所以你写x2就可以表示λx.x2,而不需要显式的写出“λx”。殊不知这些约定俗成,看起来貌似可以让你少写几个字,却造成了许许多多的混淆和麻烦。比如,你在Mathematica里面可以对 x2+y 求关于x的导数,而且会得到 y'(x) + 2x 这样蹊跷的结果,因为它认为y可能是一个函数。更奇怪的是,如果你在后面多加一个a,也就是对x2+y+a求导,你会得到 2x!那么 y'(x) 到哪里去了?莫名其妙……

相对而言,程序语言就严谨很多,所有的程序语言都要求你必须指出函数的参数叫什么名字。像x2这样的东西,在程序语言里面不是一个函数(function),而只是一个表达式(expression)。即使 JavaScript 这样毛病众多的语言都是这样。比如,你必须写:

那个括号里的(x),显式的声明了变量的名字,避免了可能出现的混淆。我不是第一个指出这些问题的人。其实现代逻辑学的鼻祖Gottlob Frege在一百多年以前就在他的论文“Function and Concept”里批评了数学家们的这种做法。可是数学界的表达方式直到今天还是一样的混乱。

很多人学习微积分都觉得困难,其实问题不在他们,而在于莱布尼兹(Leibniz)。莱布尼兹设计来描述微积分的语言(∫,dx, dy, …),从现代语言设计的角度来看,其实非常之糟糕,可以说是一塌糊涂。我不能怪莱布尼兹,他毕竟是几百年前的人了,他不知道我们现在知道的很多东西。然而古人的设计,现在还不考虑改进,反而当成教条灌输给学生,那就是不思进取了。

数学的语言不像程序语言,它的历史太久,没有经过系统的,考虑周全的,统一的设计。各种数学符号的出现,往往是历史上某个数学家有天在黑板上随手画出一些古怪的符号,说这代表什么,那代表什么,…… 然后就定下来了。很多数学家只关心自己那块狭窄的子领域,为自己的理论随便设计出一套符号,完全不管这些是否跟其它子领域的符号相冲突。这就是为什么不同的数学子领域里写出同样的符号,却可以表示完全不同的涵义。在这种意义上,数学的语言跟Perl(一种非常糟糕的程序语言)有些类似。Perl把各种人需要的各种功能,不加选择地加进了语言里面,造成语言繁复不堪,甚至连Perl的创造者自己都不能理解它所有的功能。

数学的证明,使用的其实也是极其不严格的语言——古怪的符号,加上含糊不清,容易误解的人类语言。如果你知道什么是Curry-Howard Correspondence就会明白,其实每一个数学证明都不过是一段代码。同样的定理,可以有许多不同版本的证明(代码)。这些证明有的简短优雅,有的却冗长繁复,像面条一样绕来绕去,没法看懂。你经常在数学证明里面看到“未定义的变量”,证明的逻辑也包含着各种隐含知识,思维跳跃,非常难以理解。很多数学证明,从程序的观点来看,连编译都不会通过,就别提运行了。

数学家们往往不在乎证明的优雅性。他们认为只要能证明出定理,你管我的证明简不简单,容不容易看懂呢。你越是看不懂,就越是觉得我高深莫测,越是感觉你自己笨!这种思潮到了编程的时候就显出弊端了。数学家写代码,往往忽视代码的优雅性,简单性,模块化,可读性,性能,数据结构等重要因素,认为代码只要能算出结果就行。他们把代码当成跟证明一样,一次性的东西,所以他们的代码往往不能满足实际工程的严格要求。

数学里最在乎语言设计的分支,莫过于逻辑学了。很多人(包括很多程序语言专家)都盲目的崇拜逻辑学家,盲目的相信数理逻辑是优雅美好的语言。在程序语言界,数理逻辑已经成为一种灾害,明明很容易就能解释清楚的语义,非得写成一堆稀奇古怪,含义混淆的逻辑公式。殊不知其实数理逻辑也是有很大的历史遗留问题和误区的。研究逻辑学的人经常遇到各种“不可判定”(undecidable)问题和所谓“悖论”(paradox),研究几十年也没搞清楚,而其实那些问题都是他们自己造出来的。你只需要把语言改一下,去掉一些不必要的功能,问题就没了。但逻辑学家们总喜欢跟你说,那是某天才老祖宗想出来的,多么多么的了不起啊,不能改!

用一阶逻辑(first-order logic)这样的东西,你可以写出一些毫无意义的语句。逻辑老师们会告诉你,记住啦,这些是没有意义的,如果写出来这些东西,是你的问题!他们没有意识到,如果一个人可以用一个语言写出毫无意义的东西,那么这问题在于这个语言,而不在于这个人。一阶逻辑号称可以“表达所有数学”,结果事实却是,没有几个数学家真的可以用它表达很有用的知识。到后来,稍微明智一点的逻辑学家们开始研究这些老古董语言到底出了什么毛病,于是他们创造了Model Theory这样的理论。写出一些长篇大部头,用于“验证”这些逻辑语言的合理性。这些问题在我看来都是显而易见的,因为很多逻辑的语言根本就不是很好很有用的东西。去研究它们“为什么有毛病”,其实是白费力气。自己另外设计一个更好语言就完事了。

在我看来,除了现代逻辑学的鼻祖Gottlob Frege理解了逻辑的精髓,其它逻辑学家基本都是照本宣科,一知半解。他们喜欢把简单的问题搞复杂,制造一些新名词,说得玄乎其玄灵丹妙药似的。如果你想了解逻辑学的精华,建议你看看Frege的文集。看了之后你也许会发现,Frege思想的精华,其实已经融入在几乎所有的程序语言里了。

编程是一门艺术

从上面你也许已经明白了,普通程序员使用的编程语言,就算是C++这样毛病众多的语言,其实也已经比数学家使用的语言好很多。用数学的语言可以写出含糊复杂的证明,在期刊或者学术会议上蒙混过关,用程序语言写出来的代码却无法混过计算机这道严格的关卡。因为计算机不是人,它不会迷迷糊糊的点点头让你混过去,或者因为你是大师就不懂装懂。代码是需要经过现实的检验的。如果你的代码有问题,它迟早会导致出问题。

计算机科学并不是数学的一个分支,它在很大程度上是优于数学,高于数学的。有些数学的基本理论可以被计算机科学所用,然而计算机科学并不是数学的一部分。数学在语言方面带有太多的历史遗留糟粕,它其实是泥菩萨过河,自身难保,它根本解决不了编程中遇到的实际问题。

编程真的是一门艺术,因为它符合艺术的各种特征。艺术可以利用科学提供的工具,然而它却不是科学的一部分,它的地位也并不低于科学。和所有的艺术一样,编程能解决科学没法解决的问题,满足人们新的需求,开拓新的世界。所以亲爱的程序员们,别再为自己不懂很多数学而烦恼了。数学并不能帮助你写出好的程序,然而能写出好程序的人,却能更好的理解数学。我建议你们先学编程,再去看数学。

如果你想了解更多关于数学语言的弊病以及程序语言对它们的改进,我建议你看看这个Gerald Susman的讲座

6 7 收藏 32 评论

相关文章

可能感兴趣的话题



直接登录
最新评论
  • BurnellLiu 程序员 2015/12/08

    矫枉过正的感觉

  • 大廖   2015/12/08

    真能瞎扯,你看看几位计算机科学大牛教授的背景再说.
    说是艺术什么的都在装逼
    计算机科学能高于数学,呵呵,真够逗的

  • 豪行天下灬   2015/12/08

    话说关于数学表达式的不严谨,窃以为是因为数学的式子是给人看的,编程语言是给电脑看的。数学里面使用各种希腊字母,是因为现代数学使用的西方的东西,西方人对于希腊字母很敏感。

  • yagao0o 二手程序员 2015/12/08

    感觉作者对数学的理解还是很肤浅
    从计算机的历史来说,起初就是为了数学计算而服务的
    学好数学并非必要,但是数学学得好,绝对是有助于更快的理解CS的

  • h8991008 无职业 2015/12/08

    专门登录上来评论:大赞!特别是最后一段

  • 随风巽命 学生 2015/12/08

    首先作为数学系的学生,我表示数学家是既严谨(逻辑),又糊涂(表达),这就导致什么呢,数学的各类话语,总是"简洁"到让人想撕书,为何?因为数学家都是高傲的,认为自己才是正确,所以我为何要和他人一样?所以证明一个定理,你可以有无数种写法,少一句漏一句大家都把你当神看,也就弥补过去了,实际上缺了那一句哪里行?

    最简单的例子,大学里最基础的求极限,一道题可以有无数种写法。因为数学根本没有限定你怎么放大!也许这是发散思维的好事,但是对初学者(浅学者)简直就是糟糕透顶,因为他们可能永远无法在第一次算的和答案一样(潜意识里认为,和答案不一样就是错的)!

    我同样喜爱编程,编程给我的感觉就是一个词,严谨,没有其他词语更好的形容了,就真的是艺术,人类发明出来的一种伟大的抽象表达方法之一就是编程语言,这回帮你把关的不再是稀里糊涂的人类了,而是一丝不苟的计算机。

    计算机科学家也就是数学家换了一个称呼而已,但是成为了计算机科学家的数学家绝对不愿意再转身回去了,因为编程语言太有意思,深深的被这种抽象艺术迷住。。写的太多

  • 93吸血鬼 学生 2015/12/08

    胡扯!

    • 王垠的水平比你高到不知道那儿去了。我也没看出他在攻击数学本身。目前数学的语言体系确实有问题,人家提出来就把你给点炸了,哈哈。

      • 93吸血鬼 学生 2015/12/09

        我确实是不如王垠。我也没看出他在攻击数学本身。我就是觉得他说的不对。他提出来我为什么要炸?笑点在哪里?

        • zer0Black 移动方向全栈工程师 2015/12/09

          他观点中有哪些是有问题的,能指明一下么?

          • 93吸血鬼 学生 2015/12/09

            部分观点,我回复在下面的评论里面了,还有些没提到的点,是我不擅长写东西,写出来和想的有偏差,更重要的是我懒。

    • 随风巽命 学生 2015/12/10

      谢谢你的意见

      • 93吸血鬼 学生 2015/12/10

        我只是看不惯有些人白受过高等教育却没有一点思想,简直民族悲哀!他王垠发过几篇论文就是上帝,说的话就是圣经啦?一副红卫兵的嘴脸。

  • Cmder Cmder 2015/12/08

    我觉得如果想搞一些高深的东西,数学是必须的!但作者说的也不错,本来很多东西就是数学家f发明出来的,在当时看起来没问题,而现在不一定了!

  • An-October-Sunrise   2015/12/08

    我能说我很后悔看了这篇文章吗?误人子弟!
    数学只有公式吗?数学逻辑、数学思想呢?
    计算机科学只有语言吗?算法、编程思想呢?

  • Int_Null   2015/12/09

    建议大家先去百度搜搜王垠的学术背景再考虑他是否是瞎扯,而且在发表见解的时候更多的是提出自己的看法和认识,而不是直接否定别人的立场,求同存异嘛~

    • 93吸血鬼 学生 2015/12/09

      嗯,那我就对号入座了,专门写长回复回应

    • 王垠的想法确实比较特别,有的人会觉得偏激,但个人认为他只是切中要害,并没有因为怕得罪备受推崇的那些大牛以及他们的追随者,而加以拐弯抹角的修饰。王垠的文章几乎每一篇我都读过,他是一个自视甚高的人,但他有这个资本。他的每篇文章的观点并不是毫无道理,相反常常是别人注意不到的细节和追根溯源之处。反而是批评他的人,看到他的行文和观点惊世骇俗,就觉得他在推翻经典,进而开始一番奇怪的逻辑——“你有什么资格作此评论?”。至此,我想引用的一句话是,难道我要评价电冰箱还得自己会制冷?——更何况,迁移到编译领域,对于这个问题,王垠确实算得上会制冷。

    • 另外,个人一直觉得王垠是最有可能获得图灵奖的一个中国人,如果他打算追求这个奖的话,毕竟他曾经写了一篇文章几乎推翻了图灵80%的神话。

  • 奔跑的ksun 软件工程师 2015/12/09

    已经把微积分高数什么的忘光了....

  • ailisp   2015/12/09

    专门注册一个账号来评论,只能说这篇文章说的太了。我是数学与应用专业大四学生,研究生要去学CS了。认为作者不对的注意作者批评的是数学语言,不是数学。数学的严谨不能和程序的严谨相比,我觉得就是因为它的表达有一些漏洞,数学分析领域比如偏微分和泛函语言极不统一,如果没看过,拿起两本内容一样的书都得半天才对的上。看懂一个定理的证明比别人给你讲这个定理往往要多用数倍的时间,即使证明写的很完善。一个写的过得去程序就不是这样,你看一遍肯定不想让一个人给你讲一遍。对于我觉得数学语言完善一些的领域,比如代数,数论,拓扑,那看着赏心悦目,表达似乎能赋予不是那么天才的人洞察问题的本质的能力。另外,数学系的教授写的程序确实不能和程序员相比也是实话

  • 93吸血鬼 学生 2015/12/09

    既然有人说我炸了,那我就多说两句嘛。本来就是闲逛,懒得打那么多,非要逼的跟知乎一样。

    细的我就不说的,说说几个论点。
    *数学不是计算机科学的基础*。这个看你怎么理解,我认为是,肯定是。科学是科学,工程是工程,相辅相成,但是却不是一回事。写代码就是懂计算机科学了吗?不是。懂计算机科学就会写代码了吗?也不是。我见过学到计算机博士的人不会写一行代码,也见过撸代码好几年还分不清抽象数据类型和数据结构的人。培训机构两个月速成的会写代码吗?写的比认真上四年大学的学生还要好,但是他懂计算机科学了吗?真的要好好考量一下。所以,数学不是计算机科学的基础?那需要讨论一下数学是什么科学的基础的复杂问题了。

    *数学是异常糟糕的语言*。数学是语言本身就是异常糟糕的论断,你捧他一万次这句话我也敢踩在地上捻。数学就是x^2吗?数学就是++--><吗?显然不是。(当然你也可以坚持是,那我们可以终结这个话题)。可以这么说,数学从来没有解决过任何实际问题,现在的各种高科技都是其他学科的成果,数学没有任何实体,数学是一种思想,这种思想存在与所有的学科,甚至生活的智慧(书生唱不过刘三姐是咋回事来着?)。教你方程不是要你买菜去求解的,教你1+1=2不是要你去数棒棒糖的,教你离散余弦变化也不是让你臭显摆的。你就不能体会到为什么只有方程才能解决这个问题吗?为什么1+1不能等于3吗?为什么离散余弦变换会把数据压缩吗(诶,好像论点不对)?

    说完数学是语言这码子事,我们来讨论一下语言的问题。数学语言有问题!大大的有问题,但是语言不过是表达思想的工具,你不高兴你不这么写不就行了,你面对面和他说明白不可以吗?(你说发论文不让这么写?拜托既然你从事了这个行业,起码的规矩要有吧!)数学家表达乱,书往前翻个几十页总能找到某个地方说明了这个写法的含义吧。然后*你以为计算机科学的语言就不糟糕啦!**你以为计算机科学的语言就不糟糕啦!**你以为计算机科学的语言就不糟糕啦!*,我就不说你JS的标准有多混乱,各个平台的差异有多扯淡,标记语言的统一都折腾了半个世纪现在还不是这个鬼样子,论坛里那些个程序员天天吵某某语言怎么好怎么烂,你见过数学工作者这么大规模的吵?最后,你家的伪代码有标准吗?

    *关于标准的话题*,数学发展了那么几千年,助记符全世界都不一样,今天能够达到这个水平确实不错了,想想计算机的编码,各自为政,多少工作花费在编码转换上。一个说英语的数学家和一个说中文的数学家可以不说一句话完成以此交流。你让一个说中文的程序员和一个说英文的程序员交换一下文档试试?你连注释都看不懂!你还要注释,你见过数学要注释吗!(不好意思,过了,有点回不来)我在试图说明你不能理解的东西并不代表他很烂。

    *数学家不在乎证明的优雅性*,提出来单踩。搜搜有多少人,多少种方法证明过毕达哥拉斯定理(既然把我放到左派阵营了,那我就脱离中庸知道,此处必须高逼格并做到旗帜鲜明)。

    *编程是艺术*四肢高举的赞同,然后补充一下。数学是艺术,化学是艺术,物理是艺术,语文是艺术,体育是艺术,艺术是艺术,你要高兴我可以写三天三夜不带重样的。

    • Elixir 研习 2015/12/09

      > @王垠:数学的理论很多是有用的,然而数学家门用于描述这些理论所用的语言,却是纷繁复杂,缺乏一致性,可组合性(composability),简单性,可用性。这也就是为什么大部分人看到数学就头痛。这不是他们不够聪明,而是数学语言的“设计”有问题。

      blog不是paper!你可以喷淫王博文段落的小标题措辞不严谨(毕竟不是paper),但请耐心看过整个小节,人家表达的是“数学语言设计有问题”。再者数学水平很一般,依旧不妨碍你成为一名出色的程序员!

  • Rye-Catcher   2015/12/09

    感觉说的挺好
    数学的符号系统确实既混乱又没有什么表现力
    计算机科学与数学结合会有很好的产物
    可数学并不是计算机科学的坚实基础

  • 随风巽命 学生 2015/12/10

    我写完评论就知道有人会来黑。
    但是又怎样,我永远是数学系的学生,我永远高傲,为什么要从一开始就认为自己不如别人呢,这种思维就像做课本上的课后题,你一定知道有答案,那你做完会去对答案吗?我不说我的做法,你也不必说。心里清楚就好。
    其次,我炸数学?谁有资格炸数学。我只是在说数学的表达方式,要是我写多了反而是我在挑起事端,有何意义,不如多讨论一些数学的现代形式更有意义,而不是说我是否在黑或者炸数学。

  • fetag   2015/12/11

    无知者无畏啊!自己坐在井里面,就信誓旦旦的说天只有井口那么大,也是醉了~~

  • 子不语   2015/12/11

    无知者无畏,你以为自己很NB,所以你永远只是一个码农

  • 他批评的是数学语言,而不是数学。

  • 云赟重生 编程 2016/01/05

    我是数学系的哦 表示毕了业才发现数学美了 不怕发现的晚。庆幸当时不知道数学的用意所在还是坚持学了

  • Lellansin   2016/06/03

    写得挺好。数学的表述确实很乱,大部分人还没能体会数学的美就被耗死在了路上(包括我)

跳到底部
返回顶部