數值分析讀書筆記(4)求非線性方程的數值求解

數值分析讀書筆記(4)求非線性方程的數值求解

1.關於非線性方程的根的定位以及二分法

我們直接介紹二分法

將有根區間 [a,b] 用中點 x0=a+b2 將它平分, 如果x0 不是f(x) 的零點, 則再做搜索, 檢查f(x0)f(a) 是否同號, 然後即可知根落在左側還是右側, 用這個中點來代替掉原來的端點, 然後得到一個新的區間, 如此反覆迭代下去之後, 我們會發現區間收斂到接近一個數

二分法簡單易懂,我們只要不斷去計算中點,然後判斷符號,從而來判斷根的位置
但是二分法有着收斂速度慢的缺點,我們一般是用二分法來找到一個合適的初始值,然後再用其他收斂速度比較快的算法進行計算

我們可以用代碼來實現一下二分法

public class NumericalTest {
    public static void main(String[] args){
        double a=0,b=2,mid=(a+b)/2,fa,fb,fmid;
        for(int i=0;i<100;i++){
            System.out.println(mid);
            fa=function(a);
            fb=function(b);
            fmid=function(mid);
            if(fa*fmid>0){
                a=mid;
            }else{
                b=mid;
            }
            mid=(a+b)/2;
        }
    }
    public static double function(double x){
        return Math.pow(x,3)+2*Math.pow(x,2)-4;
    }
}

給出最後的輸出結果

1.1303954347672787
1.1303954347672787
1.1303954347672787
1.1303954347672787
1.1303954347672787
1.1303954347672787
1.1303954347672787


2.基於不動點原理的迭代法

類似於之前關於迭代法求解線性方程組時所講過的Gauss-Seidel迭代以及Jacobi迭代等迭代的方法,我們對於非線性方程也可以使用這種基於不動點原理的迭代法,這時我們的目的即是構造出一個等價的非線性方程

x=φ(x)

我們用簡單的代碼來模擬一下

public class NumericalTest {
        public static void main(String[] args){
            double x=0;
            for(int i=0;i<100;i++){
                x=function(x);
                System.out.println(x);
            }
        }
        public static double function(double x){
            return Math.sqrt((4-Math.pow(x,3))/2);
        }
}

上面的代碼是對f(x)=x3+2x24=0 進行轉換, 並且建立迭代格式

x(k+1)=(4(x(k))32)12

最後可以看出來應該是收斂的,給出最後的幾個輸出

1.1303954901953999
1.1303953877755042
1.130395474606742
1.1303954009915165
1.1303954634022533
1.1303954104906446

這裏給出不動點迭代的三個基本要求

  • 適定性: 要保證序列{xk} 始終在ϕ(x) 的定義域中,才能使迭代不中斷
  • 收斂性: 要求迭代收斂
  • 收斂率: 要求收斂速度儘可能高

接下來我們來研究一下不動點的存在性以及迭代法的全局收斂性

關於不動點的存在性,給出一個Lipschitz條件,且給出不動點存在與唯一性定理

設迭代函數φ(x)C[a,b] , 且同時滿足
1. 定義域條件: φ(x)[a,b] , x[a,b]
2. Lipschitz條件:存在Lipschitz常數 0<L<1 ,使得對任意t,s[a,b]

|φ(t)φ(s)|L|ts|

則不動點迭代函數φ(x)[a,b] 上存在唯一的不動點x

需要注意的是,這是不動點存在且唯一的一個充分條件,卻不是必要的,
也就是說如果不滿足這兩個條件或不滿足其中一個條件者,可能存在不動點

下面給出不動點迭代收斂與誤差估計的定理

設迭代函數φ(x)C[a,b] 滿足上述的定義域條件以及Lipschitz條件,則對任意的x0[a,b] , 由不動點迭代格式產生的序列{xk}k=0 必收斂於φ(x) 的不動點x ,並有誤差估計

|xxk|Lk1L|x1x0|

|xxk|L1L|xkxk1|

上述兩個不等式,有時稱前者爲先驗估計,後者爲後驗估計

利用上面的不等式,我們可以計算出給定誤差界限所需要迭代的步數

nln(ϵ(1L)|x1x0|)lnL

其中ϵ 爲給定的誤差界限

給出一個推論

設迭代函數φ(x)C[a,b] , dφdx[a,b] 上有界,且

|dφdx|L<1,x[a,b]

則之前給出的不動點唯一定理以及後續的收斂定理均成立

以上給出的條件可能是基於全局收斂的,如果滿足的條件只是限制在某個領域之中的話,那麼就是局部收斂,對於局部收斂,也只需證明局部滿足上述條件,需要提一下的是,不動點的迭代方案,在全局的情況下屬於線性收斂

3.Newton切線法

解非線性方程組,除了我們之前講述的迭代法以及二分法,還有Newton切線法,這一種方法是解非線性方程組常用的有效方法,特別的,當初始值充分接近方程的根的時候,收斂的很快,基本思想是以直代曲,近似成線性方程來求解,下面給出迭代的格式

xk+1=xkf(xk)f(xk),k=0,1,2,

這裏直接給出代碼來進行模擬

public class NumericalTest {
    public static void main(String[] args){
        double x=1;
        for(int i=0;i<20;i++){
            System.out.println(x);
            x=x-(function(x)/function2(x));
        }
    }
    public static double function(double x){
        return Math.pow(x,3)+2*Math.pow(x,2)-4;
    }

    //求導後的函數
    public static double function2(double x){
        return 3*Math.pow(x,2)+4*Math.pow(x,2);
    }

}

比起二分法或者迭代法,它的收斂速度還是較爲快速的,特別是當初始值接近根的情況,更加明確的說,Newton切線在充分接近單根的情況下二次收斂,其他情況下線性收斂,充分接近重根的情況下線性收斂

下面針對Newton切線需要計算導數的這一缺點,給出另外一種類似的方法,即割線法

這裏直接給出迭代的格式

xk+1=xkf(xk)f(xk)f(xk1)(xkxk1),k=1,2,

給出代碼的實現

public class NumericalTest {

    public static void main(String[] args){
        double x1=1,x2=0,temp;
        for(int i=0;i<20;i++){
            System.out.println(x2);
            temp=x2;
            x2=x2-(x2-x1)*(function(x2)/(function(x2)-function(x1)));
            x1=temp;
        }
    }

    public static double function(double x){
        return Math.pow(x,3)+2*Math.pow(x,2)-4;
    }
}

割線法的速度也是十分快,而且避免了導數的運算

對於非線性方程求根還有同倫算法,擬牛頓法等,待補充

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章