第一节:方程式求根
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第一节:方程式求根
一元方程式求根或者说解方程是所有求值运算中最简单的一类。
通常中学数学教会你如何直接求出一元一次和一元二次方程的根,三次和四次方程的求根公式复杂一些,但也不超过高中数学的水准。
然而五次以上的方程并没有通用的求根公式,为了求解这种方程,通常必须使用数值近似。
除了代数方程之外,很多时候还会碰到超越方程,例如当你学习初等量子力学的时候,你就会碰到有限深势阱的本征方程,它可以写成这样的形式:
x k x k 21)tan(=
这个方程因为同时出现了多项式和初等超越函数,是不可能用有限的方法得出其根的。
让我们从一个蹩脚的评述开始,实际上,一元方程的求解是个“基本被解决的问题”,即使是多元方程,只要方程不太多,你用现成的比如Mathematica 之类的软件都能求出根来。
即使是我,也建议你干脆用这类东西来进行求根。
既然如此,为什么仍然需要讨论解方程的技巧呢?原因是会有一些比较复杂还不适合用现有的数学软件来处理的问题的求解法中间要用到解方程。
而你在自己写的程序中调用Matlab 或者Mathematica 函数来做一个小规模运算通常不是个好主意,它会严重的影响程序的性能和维护性。
所以,开始吧!
一般来说,一元方程的求根总可以写成一个f(x)=0的形式,其中f(x)是某个任意函数。
如同你在数学分析里面学到的,函数f(x)只是一个映射,它对任何一个x 值产生出一个函数值,而我们的任务就是去搜索一个x 值使得它的函数值为0。
在现在这个阶段,我们限制在x 和f(x)都是实数(函数)的情形。
很明显,由于实数的稠密性,永远不可能得出x 的准确值,因此我们能做的只是通过一组手续逐步去逼近x 的准确结果。
此外,由于超越函数方程并没有类似代数方程的根的个数定理,因此也很难判断到底一共求几个根才算满足要求了。
一元方程的求根法,最重要的基础是关于函数连续性的基本定理:假设f(x)是个连续函数,且存在两个实数a<b 使得f(a)<0,f(b)>0,那么必然存在一点z 位于[a,b]中(a<z<b)使得f(z)=0。
这个定理用起来非常简单,如果你找到了满足上面条件的a,b 两点,那么你可以在a.b 之间选择另外一个点c ,并且计算f(c),显然如果f(c)和f(a)同号,那么[c,b]之间存在一个根z ,否则在[a,c]之间存在根z’。
接下来你又可以对[c,b]执行同样的操作,如此反复,很快就可以得出关于根的一个估计值。
这个方法是有效且几乎是普适的,为了找到一对[a,b],你可以直接从任何一个点a 开始,不断地计算a+d,a+2d,。
直到f(a+nd)和f(a)反号。
问题只是,在已知[a,b]的情况下如何去产生新的c 值。
最简单的考虑当然是取c=(a+b)/2,不过这个方法效果不太好(你可以自己考虑一下为什么)。
比较明显的改进是连接{a,f(a)}和{b,f(b)}两点,并且求出这条连接线和x 轴之间的交点。
理由很简单,求解f(x)=0只是找y=f(x)和y=0的交点,如果a 和b 已经很接近,那么y=f(x)会很接近于一条直线,于是用局部的线段近似找到的交点会非常接近于真实的交点。
这个做法称为弦割法。
把曲线的局部用线段来近似是解决数值问题的基本概念之一,前面的做法相当于用弦来近似曲线,很显然,微积分中还有一种近似手段,就是用切线来近似曲线。
这个替换手法产生了一些意想不到的优点:要确定一条弦,你必须设置两个端点,而设置切线只要确定曲线上的一点就可以了,切线斜率可以通过对函数f(x)求导得出。
于是,你需要做的是,给定曲线上
的一点a,计算f(a)以及f’(a),得到这一点的切线方程,然后求出切线和数轴的交点b,计算x=b 处的函数值以及导数值,如此重复下去。
这个方法叫做牛顿法。
如果函数f(x)在零点处的行为足够好,同时你选择的a 值离真实的根值很接近的话,这个操作方法会很快的得到一个令人满意的近似根。
但它和前面的弦割法不同,对于一般的函数f(x),没有什么数学定理保证这个方法一定能得到结果(术语叫做:收敛)。
最好用的收敛定理大致是这样的:如果在区间a,b 上,f(a)f(b)反号,在整个区间内,f’’(x)不变号,f’(x)不等于0,区间内存在一点c,使得f(c)f’’(c)>0,那么从c 点开始的牛顿法必定收敛于一个根。
关于解这类方程还有一些手法,但前述牛顿法和弦截法是基本的,其他方法只是提高其执行效率和可行性而已。
此外,还存在一种非常常用的(笨拙)的技巧,称为简单迭代法。
简单迭代法的概念如下,考虑方程)exp(x x −=。
一个有启发性的解法是这样的:随便给一个x 值,例如x=1,直接把上述方程看成从右端计算出一个新x 的过程,那么,我么得到一个新的x 值(大约是0.6),继续把这个x 值代入右端,产生出一个新的x 值,反复执行若干次,就得出对根的一个很好的估计。
这个方法什么情况下才能产生出收敛的结果呢?其实确定一个迭代手法的收敛性是很困难的,最基本的定理是所谓压缩映射定理:你可以把在[a,b]上的迭代操作x=f(x)看做一个变换,因为对于每一个x 值,都会产生出一个f(x),当f(x)连续的时候,它就把整个区间[a,b]变换到了另外一个区间[fmin.fmax]。
假如每次变换都能保证变换后的f 区间满足|fmax-fmin|<q|b-a|,其中q 是个小于1的正数,那么经过无穷多次的变换后,区间长度趋于0,其中一定包含且只包含一个点,这个点就是需要的根。
当然,这个定理用起来不是很方便,没有关系,我们仍然可以运用导数方法来强化它:如果在区间[a,b]内f(x)处处可导且一阶导数|f’(x)|<q ,其中q<1,那么这个x=f(x)的迭代是收敛的。
因为任何迭代法本质上都是x=f(x),所以这个强化后的定理很有用。
最后,如果这些迭代方法收敛得不够快,我们还可以应用一些加速手段,这类加速方法在计算机计算能力还很弱的时候很流行,但在今天,我们已经很少用这类东西了。
尽管如此,如果你想了解这种加速技术的细节,可以找任何一本数值方法的参考书。
一元方程的求根是个研究得比较透彻的问题,毕竟用暴力搜索法总能找到一个合理的根(除非根不存在)。
但当扩展到多元方程的时候,问题就变得极其困难。
事实上,最有效的方法是牛顿法的直接推广。
我们回到牛顿法,假设在某一点,函数值是f(x),导数是f’(x),那么牛顿法预测的下一个迭代点x’要满足
)('')(x f x
x x f −=− 换句话说,令x x x δ+=',牛顿法可以看成求解方程
)()('x f x x f =δ
的过程,这个方程当然也就是0)(')(=−x x f x f δ
现在把牛顿法推广到多元,考虑2元的情况,对于一个非线性方程组
⎩
⎨⎧==0),(0),(y x g y x f 我们从任何一点00,y x 开始,
建立起z=f(x,y)和z=g(x,y)的切平面,我们知道这两个切平面方
程就是
)),(()()(0000y x f z y y y
f x x x f −=−∂∂+−∂∂ 以及
)),(()()(0000y x g z y y y
g x x x g −=−∂∂+−∂∂ 两个切平面相交于一条直线线,这条直线线和z=0的平面相交的交点可以直接通过在上面方程中设置z=0给出。
这样我们就得到确定T
y x x },{δδδ=的方程: F J −=⋅δ
其中T
y x g y x f F )},(),,({0000=
而J 是雅可比矩阵 ⎥⎥⎥⎦
⎤⎢⎢⎢⎢⎣⎡∂∂∂∂∂∂∂∂=y g y f x g
x
f J 这样就得到一组二元一次方程组,其解法是初中数学中知道的。
于是,我们需要做的是,从任何一个点00,y x 开始,计算雅可比矩阵,求解二元一次方程组,得到T
y x },{δδδ=,然后⎩⎨⎧+=+=y y y x x x δδ0101,得到一个新的猜测点11,y x ,重复上述操作,直到得出一个近似解。
很明显,这个方法具有和一元牛顿法类似的缺点,只有初始猜测很接近真正的解的时候,这个迭代过程才收敛;此外,如果我们把这个办法推广到更高阶的方程的时候,会碰到越来越大的线性方程组求解问题。
第三,这个计算方法需要不断的计算f,g 函数的导数,在f,g 函数没有解析表达式的时候,这个计算可能是很困难的。
第一个问题的处理需要用到一些新的思路,我们会在研究极值问题的时候考虑;线性方程组的求解是数值方法中的一个重大门类,我们以后再介绍;第三个问题只能想办法绕过,比如,我们可以用差商来代替导数,这就得到割线方法。