[转]数学是一种思考方式
一篇不错的文章,转一下,大家共享之
这几天有个读者来来去去给我写了几封 email ,问起我的观点:数学和编程是什么关系?学编程需要多深的数学基础?到底需要掌握哪些数学知识,对编程能力的提高有帮助。
这个还真不好说。
如果说起课堂上我们学到的知识。除了初等代数,在编程中我还真没碰到多少依赖数学技能来解决的问题。当年我学 C 语言的时候很小,甚至不知道数学中函数这个概念,还不一样把 C 语言学完了。虽然过了些年,我才把数学中的函数和程序中的函数联系起来。
做 3d 游戏编程,大学里的线性代数可能还用的到一点。至少得知道矩阵运算吧。但是大部分程序员并不需要接触这些东西。除此之外,如果说程序员必须精通微积分才能编程,那绝对是鬼扯。
如果对用编程的手段解决各种问题感兴趣,或许相关领域的数学知识有些用。比如我时常由于兴趣,做一些数据统计分析工作,这时概率统计的知识就少不了。但是解决问题,编程和数学一样,都只是工具。他们的地位是平等的,并非编程的技能依赖数学技能。
那么,学习数学有用吗?当然有必要。因为数学是一种思考方式,编程需要这样的思考方式。
我有个朋友,十年前认识他的时候,他说他在学佛。有一个问题没弄明白:佛说,不要执着。那么执着于不要执着是不是一种执着。
过了好些年,他还没弄明白这个问题。
学佛怎可以执着于这样的语言逻辑呢?光读佛经是没有用的,道理有时候需要顿悟。数学也如此。
学习数学绝对不是无休止的解题训练,我们需要悟到其中的思考方法。那种逻辑严密的推理,对完美境界的构建。发现理论上的缺陷,并对其分析,重新构作。当然,这个过程,又需要我们做大量的练习,借此领悟其中的道理。
编程也一样,不断的编写代码本身并不能直接提高编程能力。我们需要的是对问题的洞察力,构建系统的能力,理解机器运行时来龙去脉的能力,等等。而这些能力又是在不断编程实践中顿悟出来的。
编程和数学一样,是绝对严谨的。程序有特定的输入,经过特定的流程,一定有特定的输出。对于程序中的 bug ,我们不能抱有神秘论。它们不会没来由的出现,没来由的消逝。这就跟数学证明一样,逻辑或概念的缺陷不会随着时间消失,总等待后人来修补。
另一方面,在数学中,直觉也是很重要的。直觉可以帮助我们快速理解问题,解决问题。对数学了解的越多,数学的直觉就越准。很多数学知识,不需要太多研究学习,靠直觉就可以理解了。程序写多了的人通常也会有这种感觉 :D
只是有时候,数学中有些命题很直观,但是证明过程却非常繁杂。
比如拓扑学中的若当曲线定理:平面上一条简单闭曲线 C 恰好可以把平面分成两个区域,一个是内部,一个是外部。换句话说,平面上的点被分为了两类:在曲线外部的点集 A,和在曲线内部的点集 B 。在同一点集中的任意两点都可以用一条不与 C 相交的曲线相连,而连接一对不属于同一点集的两点的连线必然和 C 相交。
这个定理看起来很直观,显然是对的。但是一般人很难做出严格的数学证明,甚至很难看懂其证明。
现代编程我们经常会遇到类似的东西。尤其在现在系统越来越复杂的情况下,一段很简单的应用程序代码,你可以很显然的知道它能做什么,但是很少有人可以完全解释清楚它是怎样一步步做到的。比如一段很简单的 Windows 程序代码就是这样。只有拥有追根问底的数学精神,才会刨进操作系统底层,去搞明白系统到底怎样工作。这些不是一日之功,甚至不是三五年就够了的。而许多庸庸碌碌的程序员,满足于拖两个控件,粘合一下代码。最终只会感叹,程序只能写到三十岁。要我说,平庸资质如我,三十岁能入门就不错啦。
数学的发展历史中,又包含了许多人无穷的创造力。光靠逻辑推理来一步步解决问题显然是不够的。很多数学问题的解决,都起源于某种直觉,某种创造性构建,甚至把许多表面不相关的东西牵连在一起思考。然后再通过逻辑严密的推导过程来完善它。
例如,费马大定理的最终证明。首先找到了关于费马方程的解所在的费马曲线和椭圆曲线的联系,然后构造出一种特殊的椭圆曲线,当且仅当费马大定理不成立时,该曲线才存在。最后,通过证明这种曲线有一些极端奇怪和不可信的性质,决定了曲线不可能存在,从而反证了费马大定理成立。这之中虽然用到了许多前沿的高深数学理论成果才得以证明,但整个思路框架之巧妙,也是让人佩服之至。
编程也是如此,我们首先需要对各种编程方法,编程语言的特性得心应手;而后,编程绝对不是简单的堆砌代码,它需要我们巧妙的构建系统,在合适的地方用合适的方式来解决问题。最终还需要让每个部分都严格正确。
最后,对于那位朋友的问题,我只能给出我的个人建议。学习编程的确需要学习数学。但学习数学,不必列出书目,一本本去啃那些枯燥的教科书。只需要从数学史读起,弄清人类是怎样一步步理解数学的,学习其中的思想,最后用自己的兴趣去研究其中感到有趣的部分。