17世纪是数学发展史上一个划时代的时期,当我们今天享受着高科技成果所带来的各种便利条件时,应该意识到笛卡儿(Descartes,1596—1650)和牛顿(Newton,1642—1727)这两位卓越的先驱人物所作出的具有划时代意义的贡献。
首先是笛卡儿创立平面解析几何,为我们开创了利用数学研究变量的新时代,使我们能用数学形式描述动态变化着的客观对象。从此生活在这个星球上的人们可以利用数学形式来描述天体运动规律以及一些非常复杂的系统的运动规律。接下来牛顿与莱布尼兹(Leibniz)等人创立微积分学,为我们研究连续变量的变化规律给出了完整的方法体系。随后,又在这个基础上产生了更多的数学分支以及相关的一些交叉学科分支。
由于数学研究的范围在不断扩大,而且研究的对象更为复杂,一个伴随的问题就是相应的数值计算更加困难。如果不解决与理论方法平行的数值计算问题,再好的数学理论也难以发挥应有的作用。牛顿的天才之处还在于,他在创立微积分学的同时,在数值计算领域也取得了具有历史意义的成就,实际上已经开始了这个领域中的奠基性的工作,这一点由数值积分的牛顿柯特斯(NewtonCotes)公式可以明显地看出来。
计算方法,过去有不少人称之为数值分析,现在更多的人称之为科学计算,其核心思想就是通过有限步的加、减、乘、除四则运算得到某个连续变量的近似值。如果我们进一步追根溯源,它应该是微积分学孕育出来的一个数学分支。当然,在计算机问世以前也只能是一个数学分支。极限论为近似计算提供了理论依据,如果一个无限序列{xn}收敛于某个极限值x*,那么我们可用这个序列中的某个元素xN作为x*的近似值。只要序号N取得足够大,那么xN与x*的差值|xN-x*|就不会超过某个预先给定的充分小的正数ε。利用泰勒(Taylor)展式,可以把某个充分光滑的实函数f(x)表示为一个项数为无限多的多项式,再利用极限理论,我们可以取这个多项式的前N项近似表示f(x),从而可以通过有限步四则运算得到f(x)的近似值。
如果说极限理论和泰勒展式为我们在更大范围内进行近似计算提供了理论依据,那么插值法则进一步为近似计算提供了实践指南。对于实际问题来说,通常需要计算某个适当光滑的实函数f(x)在某个适宜的区间/[a,b/]内的任一点处的函数值,而且不希望花费太多的计算时间。只要这个区间的长度不太大,可以事先采用其他方法计算出区间内的少量几个离散点x0,x1,…,xn处的函数值f(x0), f(x1),…, f(xn),接下来再构造相应的n次或低于n次的插值多项式p(x),并利用p(x)进行相应的计算。实际上,我们还可以利用p(x)完成关于f(x)的更多的计算,比如微分和积分,加快一个序列的收敛速度等。当我们利用函数f(x)的插值多项式p(x)求f(x)在某个点处的微分或某个区间上的积分时,相应的计算又可表示为求f(x)在一些点处的函数值的线性组合。所以只要找到这一组神奇的组合系数,接下来的具体计算就可以按机械操作的方式完成。正是因为一些看似十分复杂的数学问题,却蕴含着如此简单的求数值解方法,才使得计算方法成为一个魅力无穷的研究领域。
数值计算的重要性一方面促进了计算方法的研究,另一方面也促进了计算工具的发展。随着20世纪40年代中期人类第一台电子数字计算机的问世,数值计算终于有了理想的支撑工具。坚实的数学理论,科学的计算方法以及先进的计算工具的有机结合,可以为我们打造了一个无比坚实的工作平台。正是因为有了这样一个平台,才有了20世纪60年代人类登上月球的壮举以及今天许多国家雄心勃勃的太空开发计划。完全可以这么讲,今天几乎所有的高科技成果都是在这个平台上产生的。正是因为有了这样一个平台,从而使得我们这个时代的科学技术能够飞速发展。
今天,我们正处在一个非常有利的历史时期:过去,以牛顿为代表的一大批先驱人物在当时的计算工具极为落后的条件下进行了大量的研究,取得了丰硕的成果,为我们留下了宝贵的精神财富;今天,电子计算机性能不断提升而价格又不断下跌为我们的科学计算提供了难得的物质基础;再者,当代科学技术的不断进步和生产力的迅速发展又为高水平的科学计算提供了用武之地。利用现有的计算机条件,再现以牛顿为代表的这些优秀人物的思想和方法,进一步发掘潜藏在计算方法领域中的科学真谛,完全可以期待着更加辉煌的成就。
我完全同意这一点,今天,我们具有比先前的和以后的人更好的发展机会。真的是时不我待。
数值和计算机技术的结合,已经为了在眼前展开了一幅伟大的画卷。加油呀,禾路。
作者在华中科技大学长期从事与数值计算密切相关的计算方法和运筹学等课程的教学,感触甚多。近几年来,坚持利用多媒体设备从事计算方法课的教学,又进行了不懈的探索,深刻领悟到现代计算方法课的教学对于培养大学生和研究生的综合能力以及科学研究的兴趣来说处于得天独厚的地位。通过计算方法的教学,可以帮助学生早期实现利用所学的数学基础知识应用于比较复杂的数学模型求数值解的算法研究,进而利用计算机求解相应的问题。写一本与培养目标相适应,与教学手段相适应,而且为学生留有一定的自学余地和超前引导内容的教材,既是学生的企盼,也是教师的责任。本书就是在这种背景下写成的,全书共有13章,适当选取,可适应多层次的教学需要。
实用数值计算方法前言下面简要介绍一下本书的主要内容以及写作的经过。
第1章相当于概论,主要论述利用计算机进行数值计算的重要意义和基本方法,结合本书的特点介绍了列表计算的重要意义,结合简单的数值微分算例给出了完整的列表计算源程序。鼓励读者从一开始阅读本书就与上机操作联系起来。
第2章在介绍了误差的来源和误差的基本概念后,着重介绍了利用微分估算误差和利用条件数估算误差,最后结合算例介绍了科学计算的基本规则,这也是作者编程的心得体会。
第3章主要利用基本初等函数的泰勒展式求函数值,并根据极限原理来控制误差:对于适当给定的ε>0,根据泰勒展式的余项估计公式利用计算机程序计算出相应的项数n,按照科学计算的规则求相应的n次多项式的值。所有的计算实际上都得到了利用双精度数计算所能得到的最精确的结果。这些结果一方面证实了所采用的方法的科学性,反过来又为科学计算奠定了基础。长期以来,人们总是面临这样的尴尬局面:科学计算离不开软件开发商提供的基本初等函数计算程序,而相应的源代码和算法却是商业机密。现在,科学计算终于有了属于自己的基础领地。如果说极限论中的εN规则奠定了连续变量数学的基础,那么εN规则在计算机上的实现,将会使得计算机在解决数学问题领域发挥更大的作用。
第4章函数增量的计算方法,主要解决科学计算领域最令人头疼的问题:求连续函数y=f(x)在x0处的Δx增量Δy=f(x0+Δx)-f(x0)和增量比Δy/Δx=/[f(x0+Δx)-f(x0)/]/Δx。这里所得到的结果从哲学的角度讲也是很有意义的。以计算Δy=arctan(x0+Δx)-arctanx0(1)为例,首先对Δy取正切,利用公式tan(a-b)=(tana-tanb)/(1+tanatanb)可以得到tan(Δy)=Δx//[1+x0(x0+Δx)/]接下来再对tan(Δy)取反正切,又可以得到Δy,从而有Δy=arctan(Δx//[1+ x0(x0+Δx)/])(2)通过这么一轮否定之否定,比起(1)式来说,利用(2)式计算Δy,计算量可以大大减少,计算精度可以大大提高。如果说计算量的减少属于量变,那么计算精度的提高应该属于质变。如果进一步利用(2)式并借助泰勒展式来计算Δy/Δx,还可以得到更加美妙的结果。
有此,我相信我需要掌握的东西远不是一点和一方面,这对我自己的选择有了指导作用。
在第4章中,我们正是利用基本初等函数各自特有的性质,借鉴第3章利用泰勒展式进行精确计算的方法,解决了所有基本初等函数以及多项式函数的增量和增量比的计算方法,所产生的误差主要由机器的原因和相应的数学问题的条件数所决定,与我们的方法几乎没有关系,并且在计算函数的增量比Δy/Δx时,Δx可以取零值。在这一章中,还进一步讨论了复合函数以及函数的和、差、积、商的增量和增量比的计算方法,从而解决了初等函数的这一类计算问题。作者深信,这一章的成果对读者将来从事高级应用领域的科学计算一定能够产生重大的影响。
第5章解决函数的零点和极值点的求法问题,由于求函数零点的二分法与求函数的极值点的黄金分割法都属于按比例缩小区间的搜索方法,所以放在一起学习更容易理解算法的共性。牛顿法既可以求函数的零点,也可以求函数的极值点,所以从学习效果看,把这两个问题放在一起来讨论也是合适的。在国内外同类型的文献中,对牛顿法的性能分析似乎都处理得不太好,缺少灵气,极大地影响了牛顿法的应用。在这一章中,我们特别结合凸函数的性质对牛顿法的性能进行了深入研究,在适当的假设下得出了牛顿法具有单调收敛性以及二次终结性质,这方面的一些结论比参考文献/[11/]中的相应的结果更具说服力。有了这样的理论基础,相信广大读者会让牛顿法在现代计算机条件下发挥更大的作用。关于非线性方程组求解,我们采用的是循序渐进的策略,在这一章中只作最基本的介绍,接下来在第6章中再给出一个模块程序,在第7章中利用所得到的模块程序简化了Bairstow方法求多项式复根的程序设计。
第6章主要介绍两个变元的无约束极值问题的数值解方法。对于这类问题来说,最速下降法总是研究的出发点,然后再根据最速下降法的锯齿现象寻找克服的措施,从而得到改进的方法。所给出的三部曲算法可以说是作者送给读者的一份价廉物美的礼品。价廉是指方法特别简单,大学生也看得懂,用得上;物美指的是这个方法特别好。在运筹学领域,对无约束极值问题差不多进行了拉网式的研究,偏偏把这个方法给漏掉了,作者也是借此机会了却一个心愿。原来的写作计划只是在前面一章中有这样一节,只是编程时突然感觉到应该换一种编程的风格,也是对“实用”的承诺,所以就有了这一章。同时也就有了模块化程序设计方法;有了采用三部曲算法的最优化模块程序;有了牛顿拉弗桑(NewtonRaphson)方法解非线性方程组的模块程序,有了用最优化法解非线性方程组的程序;有了Bairstow方法求多项式的复根的模块程序;也有了用最优化法求多项式的复根的模块程序。在后面(实际上在前面也有一些)的许多章节中,读者可以体验到模块化程序设计方法所带来的各种方便。
考,那不是很棒!那就不要恐惧了,赶快加油地去看吧。
有这种书真的是造作呀,可能我的一个寒假都要改变计划了。但是,我必须在此之前掌握足够的数学,算法知识,还有学习,特别是大规模学习不知道东西的能力和计划方法。我了解了
第7章多项式计算的完成看来要感谢上帝的指点。无论从哪个意义上讲,多项式计算应该是科学计算的重要组成部分。作者当然希望能在这方面有所突破,为此也阅读了不少文献,但总觉得不够理想。一个偶然的机会在参考文献/[9/]中读到了多项式的Sturm定理,兴奋不已:对一般的多项式,判定所有实根所在的区间并不困难,利用Sturm定理可以确定任意区间内的实根个数,所以能够利用Sturm定理确定多项式实根的个数以及所在的区间,在此基础上可以进一步设计一个算法,还是利用Sturm定理,把多项式的所有实根所在的区间划分为若干个小区间,使得每个区间内恰有一个实根,所有这些工作都可以交由计算机以高效率的方式完成。应用Bairstow方法求多项式的复根比求实根的效果要好一些,这样一来多项式求根的问题大体上形成了解决方案。Bairstow方法涉及到所谓的二阶综合除法,所以必须介绍原始的综合除法,现在只好称为一阶综合除法。对一阶综合除法的研究终于发现它原来还有很多应用:可以求多项式的值,可以求多项式的导数值,可以对多项式作平移变换,可以用来精确计算多项式函数的增量及增量比,从而可以与第4章中解决同类问题的方法互相印证。对于求多项式的实根来说,还有一个很大的麻烦就是重根的负面影响,如果能有效地消去多项式的重根,应用Sturm定理编程也简单得多。无论是消除重根,还是求多项式的Sturm序列,都需要用到欧几里得(Euclid)算法,所以在介绍Sturm定理之前介绍欧几里得算法,并应用于消除多项式的重根也就顺理成章。第7章的构思就这样在不知不觉中达到了理想境界,将古今中外在这个领域中的重要成果有机地融于一体。
第8章介绍线性方程组求解方法,对于一般的应用而言,采用直接方法也就可以了。这一章重点介绍了高斯(Gauss)消去法,实际上已经引导读者首先开发出一个学习、研究高斯消去法和选列主元的高斯消去法的演示系统。由于借用系统仿真的方法随机生成线性方程组,所以学习起来有点像卡拉OK厅里面的自娱自乐。为了强调实用性,另外还给出了应用高斯消去法解线性方程组的模块程序,并通过与第6章牛顿拉弗桑方法解非线性方程组的模块程序连接而证实了实用性。由于高斯约当消去法相对来说要简单得多,所以只给出两个模块程序,如果需要,读者完全能够按照学习高斯消去法的模式完成相应的演示系统的编写。
曲线拟合与多项式插值虽然同属逼近理论的应用,但两者的应用领域却大相径庭,由此导致应用程序的风格也相距甚远,所以在第9章专门介绍最小二乘法和曲线拟合,并给出了几种不同工作方式的模块程序,基本上可以应用于解决实际问题。
第10章插值方法,这部分内容在数值计算领域相对来说比较成熟,但是插值方法的应用领域正在悄悄地发生变化。在过去计算工具十分落后的条件下,插值方法主要应用于求函数的近似值,应用于制作数学用表。在现代条件下,插值方法主要应用于加速序列的收敛速度。为此,本章特别增加了灵活应用插值方法举例一节,具体介绍如何集成插值方法与二分法解非线性方程;集成抛物线插值法与黄金分割法求函数的极小值点;并通过案例的对比分析说明采用插值方法加速的意义。
第11章介绍的数值微分与外推加速方法也有多重意义。在普遍应用高性能计算机的今天,数值微分的价值在不断上升。比如说,把一个程序的输出看成是输入的函数,如果这个函数从数学的意义上讲也是可微的,那么寻找一种有效的方法直接利用这个程序求相应的数值微分很能体现数学理论和计算工具有机结合的美学价值。在这一章中,首先具体介绍了利用差商或中心差商作为微商的近似值;利用不同步长的差商产生微商的近似值序列;直接构造外推方法加速近似值序列的收敛。为了得到简单、高效而且具有普遍实用意义的数值微分方法,一方面利用泰勒展式构造高阶近似公式从而导出理查逊(Richardson)外推加速算法;另一方面又把涅维尔(Neville)的递推式插值公式改造成更为简单的通用外推格式。实际上,外推方法在数值计算领域有着广泛的应用。毫不夸张地说,现代科学计算领域的许多新成就很大程度上源自外推方法的应用。
第12章从实用性考虑,详细介绍了变步长复化型自动调整精度的系列方法:梯形系列、辛普森(Simpson)序列、柯特斯(Cotes)序列以及龙贝格(Romberg)序列。由于辛普森序列、柯特斯序列和龙贝格序列可以看成是梯形系列经过一次、两次和三次外推所形成的序列,所以这一章的内容实际上特别少:除了一些基本概念外,基本方法就是变步长复化梯形公式方法和理查逊(Richardson)外推加速方法。利用复化梯形公式和复化中点公式的关系,可以使得复化梯形公式的计算量节省一半,再加之外推方法的优越性,所以数值积分的一些其他方法的性能很难超过这里介绍的序列方法。
第13章常微分方程数值解法,这部分内容在数值计算领域相对来说比较丰富。本章前面几节结合案例计算介绍了一些实用的经典的方法如欧拉(Euler)方法,龙格库塔(RungeKutta)法,阿达姆斯(Adams)外推与内插方法,可以满足一般应用的需要。由于常微分方程的数值解方法都是按步进的方式计算,所以为了消除误差的积累还需要研究高精度或者自动控制精度的方法。在一般情况下,提高精度的途径是适当减小步长,所付出的代价是增加了计算量。为了两者兼顾,特别介绍了自适应步长的龙格库塔方法和大步长问题的外推加速方法。这里的程序都以模块的形式给出,有利于读者结合实际问题灵活应用。对于求常微分方程数值解来说,刚性问题总是一个严重的挑战,为此我们结合刚性问题的特点,介绍了Bader和Deufhard的基于修正中点公式的半隐式外推方法和我们给出的利用隐式梯形公式结合牛顿法求解的隐式外推方法,并结合案例进行了对比分析,使得针对这类问题的特殊方法更趋完善。在本章最后,我们还根据问题的特点,对各种方法的选用给出了指导性意见。
为了让本书更好地适应教学目标和教学手段,也便于广大科技人员自学,本书在写作手法方面凸现了如下一些特点。
拓宽了计算方法的基础知识,为计算方法正名。纯数学界很难接受利用计算机求极限的观点。如果真是这样的话,理论上就没有计算方法存在的合法性,因为计算方法在很大程度上都使用计算机求极限的近似值,虽然不是真值,但总比人工做出来的结果更精确。第1章、第3章和第4章使得计算方法与高等数学建立了密切的联系。这样,读者一翻开本书,即有似曾相识的亲近感觉。
博众家之长,让读者站在巨人的肩上。本书虽然篇幅不长,但极尽全力介绍这个领域中做出过创造性贡献的人们的工作。集中介绍他们处理问题的思想和方法,引导读者在今天的条件下如何在计算机上再现他们的思想和方法,并结合案例分析而形成自己独立的判断。既能虚心学习,又不盲目崇拜。所花笔墨不多,但吸取的精华却不少。
尽可能把方法处理得简单。华罗庚教授曾在一首小诗中写过,“神奇化易是坦道,易化神奇不足提”。对于数值计算来说,这无疑是金玉良言。在本书中,或者借助图形解释,或者借助生活中的常识见解把算法原理解释得简单、再简单、尽可能简单。这样的例子随处可见,从而形成了风格。对于一些典型的问题求解,采用列表计算的固定格式编程,对算法熟悉了,对程序格式熟悉了,编程也就简单了。对于复杂的问题,采用模块化程序设计方法,每个模块相对简单,而且可以反复使用。
循序渐进,步步为营。书中的内容,从所涉及的数学内容看,大体保持了数学知识的逻辑顺序关系,从所求解的典型问题看,大体保持了由易到难的顺序关系;从采用某个方法,调用某个程序的依赖关系看,也大体上是被利用的方法或程序在前,使用者在后。这样的安排,减少了学习困难,有利于循序渐进、巩固提高和综合应用。
把读者扶上马,送一程。本书采用手把手的方式教读者如何编程实现相应的算法,并给出了主要代码以及案例的计算结果。除此之外,还明确地告诉读者如何改写书中的哪个程序以适应什么样的问题,鼓励读者举一反三。
简言之,作者在本书所追求的目标就是引导读者充分利用自己学过的基础知识,创造性地借鉴牛顿等先驱人物解决复杂计算问题的思维方式以及所形成的科学方法,充分利用现有的计算机资源,去解决一个又一个复杂的数值计算问题,并在这个过程中快速成长起来。作者深信,广大理工科大学生和工程技术人员阅读了本书之后,对科学计算的领悟会上升一个台阶,通过亲自动手编程,直接利用计算机求解复杂的工程问题的兴趣、勇气和能力将会大大提高,将来面对一些复杂的数值计算问题时,肯定能够少走弯路。
前面提到过,本书是根据作者在华中科技大学多年讲授计算方法,特别是近几年采用多媒体教学的经验编写而成,可作为大专院校一般理工科各专业3~4学分的计算方法课的教材或教学参考书使用。本书致力于“实用性”并不意味着一定要给出许多工程应用的案例,而是创造尽可能好的条件,帮助读者解决好从学习计算方法的算法原理到解决实际问题的程序设计这中间可能遇到的诸多问题,然后鼓励读者自由发挥,独立地解决实际问题。这个目标看来是可以实现的,作者从学生们的试验报告来看,大都能够应用课堂学习的方法解决他们专业课程中的、科技文献中的、个人感兴趣的、家长请帮忙的各种计算问题,思路之宽阔,想象力之丰富,情绪之高昂已超出作者的预期,对本书的形成也产生了一定的影响。如果作为3学分的教材使用,可以略去第4、6、7这三章,并不影响其余各章的学习,实际上也不会影响大部分学生自学这几章的兴趣。即使作为4学分的教材使用,也要适当留下一些内容(通常是比较容易的和少量有一定难度但不作具体要求的内容)让学生自学。
在一本教科书中把数学分析、算法说明、程序说明、利用计算机程序解数学问题非常密切地联系起来,难免出现术语的混乱,主要有下面几个原因:变量既是计算机词汇,又是数学词汇,但在不同领域中的含义是不同的;数组是个计算机词汇,一般指存放数据的地方,在本书中,又必须用数组来表示(存放)数学中的许多不同对象,比如向量、序列、集合、一个变量的不同的取值的集合等;C语言的指针变量的作用相当于数组;函数在C语言程序中是一段代码,作为数学概念表示两个变量之间的依存关系,本书中有许多同名的函数既是C语言函数,又是数学函数。为了尽可能避免一些不必要的混乱,本书中通常结合算法和程序的说明对一些重要的变量和数组作出相应的解释;函数作为C语言函数引用时,一般采用函数名连同一对空括号“()”的格式,如果一定带上自变量,则一定有相应的类型说明;作为数学函数引用时,则按数学的习惯使用,如果有同名的C语言函数,则蕴含相应的函数调用,并返回所得到的结果,这与函数的数学定义并不矛盾。采用这样一些约定,再加之表述时适当使用修饰成分,基本能够保持术语的规范。在极个别情况下,读者可以根据上下文来理解。
关于数学术语和数学符号的使用,与一般数学教科书中的用法基本相同。在本书中,我们采用加粗的斜体字母表示向量,向量的上标用于标示不同的向量,而向量的下标用来标示向量的分量。如果表示某个分量的指数幂,则用括号连同幂指数的形式给出。
关于引用问题,文中的定义、定理、公式、图、表都用“节.序号”的格式编号,程序则按“章.序号”的格式编号。如果本章引用,都直接通过编号引用;如果跨章引用,则在编号前指出所在的章,比如“见第10章(3.2)式”,指的就是第10章第3节公式(3.2)。
关于程序以及编号,书中所有的程序虽然没有按软件工程的规则检测,但都通过了Turbo C 2.0的编译、调试以及简单的试运行。为了说明算法,需要把一个较大的程序分割成几块分别介绍,而调试程序时只作为一个程序调试,对于这样的程序,我们采用程序编号后面附加字母A、B、C、D…的方式介绍。所以如果不计编号后面的附加字母,那么每个程序都对应着一个调试程序。书中有一些是完整的源程序,读者可以直接输入到计算机中编译运行,首先对照书上显示的结果检测无误后,可以大胆改写,让它发挥更大的作用。为了节省篇幅,有些程序中略去了一些前面出现过的相同的或类似的代码,读者可以自己补充完整。如果读者消化这些程序有困难,可以访问清华大学出版社的网站: http//www.tup.com.cn,以寻找帮助,也可以(最好以团体的方式)直接向清华大学出版社索取完整的源代码。练习题中有些编程的问题可模仿书上的程序编写,也有一些则超过了本书作为教材使用的范围,作者也将在网上陆续作答,敬请读者关注。
与本书配套的教学课件内容包括:PowerPoint文档给出的详细教学大纲,HTML文档连同脚本程序给出的结合案例分析的算法演示系统,Word文档给出的各种专题讨论。选用本书作教材的学校和教师本人如果感兴趣,可以直接与清华大学出版社联系。如果对课件有任何意见、建议、或具体要求,也可直接与作者本人联系。
尽管作者主观上想为读者提供一本好书,也为此付出了辛勤的劳动,但客观效果应由广大读者评价,另外书中也难免有缺点和错误。恳请广大读者和同仁不惜赐教,提出批评意见。
作者的Email地址: [email protected]
甄西丰
2005年8月于华中科技大学