迭代求解非线性方程的根

数值分析编程作业1

迭代求解非线性方程的根_第1张图片
非线性方程根的迭代求解常用方法无外乎三种:

  • 二分法(思想简单,迭代速度较慢,且迭代过程并不严格递减,不能求复根)
  • 不动点迭代法(构造迭代函数,一般是线性收敛的,当迭代函数在不动点处的一阶导数为0,是超线性收敛的)
  • 牛顿迭代法(利用泰勒公式展开,是平方收敛的)
    此外还有牛顿迭代法的变种,如牛顿下山法、弦割法。

编程实现

对于该问题的MATLAB实现如下:

%迭代函数的实现
function xc = unlinear_iterSolve(  x0, tol ,option)
%不动点迭代法和牛顿迭代法的实现
%其中g为构造的迭代函数,x0为初始的迭代点,tol为判断迭代收敛的阈值
%option参数1表示为不动点迭代,2表示为牛顿迭代
    x_previous = x0;
    itr_cnt = 1; %记录迭代次数
    error = 0; %记录每次迭代的误差,初始迭代误差记为0
    disp('NO.ITER        ITER_VALUE              ITER_ERROR')
    while 1
        switch(option)
            case{
     1} %求方程1的新的不动点迭代值
                x_next = f1_sp(x_previous); 
            case{
     2} %求方程2的新的不动点迭代值
                x_next = f2_sp(x_previous);
            case{
     3} %求方程1的新的牛顿迭代值
                x_next = f1_n(x_previous);
            case{
     4} %求方程2的新的牛顿迭代值
                x_next = f2_n(x_previous);
        end
        
        if(itr_cnt ~= 1) %第一次迭代不用进行收敛判断
            error = abs(x_next - x_previous); %记录每次迭代的误差
            %if(error < tol || itr_cnt >100)
            if(error < tol || itr_cnt > 25) %当误差小于设定的阈值时,判定为收敛,退出循环
                display(itr_cnt, x_next, error);%打印出最后一次迭代得到的不动点信息
                break
            end
        end
        
        x_previous = x_next;%将该次迭代得到的迭代值保存到x_previous中去
        
        display(itr_cnt, x_next, error);%打印迭代的数值信息
        
        itr_cnt = itr_cnt + 1; %每次迭代完成后将迭代次数加1
    end
    xc = x_previous;
end

function result1 = f1_sp(x) % x^2 - 3*x + 2 - exp(1)^x = 0的不动点迭代函数
    result1 = 1/3*(x^2+2-exp(1)^x);
end

function result3 = f1_n(x) % x^2 - 3*x + 2 - exp(1)^x = 0的牛顿迭代函数
    result3 = x - (x^2 - 3*x + 2 - exp(1)^x)*(2*x - exp(1)^x*log(exp(1)) - 3)^(-1);
end

function result2 = f2_sp(x) % x^3 + 2*x^2 + 10*x - 20 = 0的不动点迭代函数
    %四种不同的构造的不动点迭代函数
    %result2 = x^3 + 2*x^2 + 11*x - 20;
    %result2 = (-2*x^2 - 10*x + 20)^(1/3);
    %result2 = 1/10 * (20 - 2*x^2 - x^3);
    result2 = 1/2 * (20 - x^3 -10*x)^(1/2);
end

function result4 = f2_n(x) % x^3 + 2*x^2 + 10*x - 20 = 0的牛顿迭代函数
    result4 = x - (x^3 + 2*x^2 + 10*x - 20)*(3*x^2 + 4*x + 10)^(-1);
end

function display(itr, x_next, error) %打印每次迭代信息的函数
    if(itr < 10)
        disp(['     ',num2str(itr), '             ', ...
                sprintf('%0.13f',x_next),'            ',sprintf('%0.9f',error)])
    else
        disp(['     ',num2str(itr), '            ', ...
                sprintf('%0.13f',x_next),'            ',sprintf('%0.9f',error)])
    end
end


测试代码:

%Homework 1
x0_1 = 1;
tol = 10^-8;
disp('Fixed Point Iteration for x^2 - 3*x + 2 - exp(1)^x = 0');
x1 = unlinear_iterSolve(x0_1,tol,1);
disp('Newton Iteration for x^2 - 3*x + 2 - exp(1)^x = 0');
x3 = unlinear_iterSolve(x0_1,tol,3);
disp('Fixed Point Iteration for x^3 + 2*x^2 + 10*x - 20 = 0');
x2 = unlinear_iterSolve(x0_1,tol,2);
disp('Newton Iteration for x^3 + 2*x^2 + 10*x - 20 = 0');
x4 = unlinear_iterSolve(x0_1,tol,4);

实验结果:

初始点的值取1

  1. 对于非线性方程(1)使用迭代法求根而言:
    可以看到不动点迭代法迭代15次与牛顿迭代法迭代4次所达到的精度相同,与不动点迭代法是线性收敛的,牛顿迭代法是平方收敛的特性相符合;
    迭代求解非线性方程的根_第2张图片
  2. 对于非线性方程(2)使用迭代法求根而言:
    可以看到不动点迭代法是发散的,这里只取了前26次迭代所得到的迭代数据,造成该状况的原因是所构造的不动点迭代函数不满足不动点迭代的局部收敛定理,即|φ^’ (x^* )|<1;相对应的,牛顿迭代法快速收敛到了一实根1.3688081上,但改变多个初值进行重复实验,均收敛到该处。原来其有两个复根和一个实根,迭代法只能收敛到实根上,这也是迭代法求非线性方程的根的一个缺陷。
    迭代求解非线性方程的根_第3张图片

你可能感兴趣的:(数理知识)