数値解析 (2 回目の継続) 3 次スプライン補間 第 2 クラス境界 完全な Matlab コード

序文

  前回の記事のリンク:  数値解析 (2) 3 次スプライン補間法 matlab プログラムでは、 自然境界条件での matlab コードのみについて言及していますが、この記事では、前の記事の他の内容を埋めて完全な 3 次スプラインを提供します。スプライン補間関数の matlab コード。
   注意: 計算原理はすべて前回の記事で述べたので、この記事では前回の内容の繰り返しは省略しますが、ここでは 3 つの境界コードが直接与えられており、各境界は例題に対応しています。原理がわからない読者は前の記事を読んでください。

  再更新 (2022.5.3) 新增: 多くの学生からの問い合わせに応じて、各セグメントの式と式の各セグメントの係数について、係数行列の各セグメントの出力を追加するようにコードを修正しました、式の各セグメントの出力。内容をよく知っている人は、新しいセクションを直接見ることができます。

1. ファーストフロンティア

代码最初の境界の Matlab コードは次のとおりです。

function [D,h,A,g,M]=three1(X,Y,y0,yn)
%        自然边界条件的三次样条函数(第一种边界条件)
%        此函数为M值求值函数
%        D,h,A,g,M输出量分别为系数矩阵D,插值宽度h,差商表A,g值,M值 
         n=length(X); 
         A=zeros(n,n);A(:,1)=Y';D=zeros(n,n);g=zeros(n,1);
         for  j=2:n
            for i=j:n
                A(i,j)=(A(i,j-1)- A(i-1,j-1))/(X(i)-X(i-j+1));
            end
         end
         
         for i=1:n-1
             h(i)=X(i+1)-X(i);
         end
         for i=1:n
             D(i,i)=2; 
             D(1,2)=1;
             D(n,n-1)=1;
             if (i==1)
                 g(i,1)=6/h(i)*(A(2,2)-y0); 
             elseif (i==n) 
                     g(i,1)=6/h(i-1)*(yn-A(i,2));
             else 
                 g(i,1)=(6/(h(i-1)+h(i)))*(A(i+1,2)-A(i,2));
             end
           
         end  
         for i=1:n-2
             u(i)=h(i)/(h(i)+h(i+1));
             n(i)=1-u(i);  
             D(i+1,i+2)=n(i);
             D(i+1,i)=u(i);             %改到这里
         end
         M=D\g;
         %M=[0;M;0];         
end

function s=threesimple1(X,Y,x,y0,yn)
%        三次样条插值函数第一类型代码 
%        s函数表示三次样条插值函数插值点对应的函数值
%        根据三次样条参数函数求出的D,h,A,g,M
%        x表示求解插值点函数点,X为已知插值点        
         [D,h,A,g,M]=three1(X,Y,y0,yn)
         n=length(X); m=length(x);    
         for t=1:m
            for i=1:n-1
               if (x(t)<=X(i+1))&&(x(t)>=X(i))
                  p1=M(i,1)*(X(i+1)-x(t))^3/(6*h(i));
                  p2=M(i+1,1)*(x(t)-X(i))^3/(6*h(i));
                  p3=(A(i,1)-M(i,1)/6*(h(i))^2)*(X(i+1)-x(t))/h(i);
                  p4=(A(i+1,1)-M(i+1,1)/6*(h(i))^2)*(x(t)-X(i))/h(i);
                  s(t)=p1+p2+p3+p4; 
                  break;
               else
                   s(t)=0; 
               end
            end
         end
end

2. 第二のフロンティア

代码今回作成した 2 番目の境界 Matlab コードには自然境界が含まれており、プログラムは次のとおりです。

function [D,h,A,g,M]=three2(X,Y,y0,yn)
%        第二边界条件的三次样条函数(包含自然边界条件)
%        y0,yn表示的是S''(x0)=f''(x0)=y0,S''(xn)=f''(xn)=yn,自然边界即条件值为0 
%        此函数为M值求值函数
%        D,h,A,g,M输出量分别为系数矩阵D,插值宽度h,差商表A,g值,M值 
         n=length(X); 
         A=zeros(n,n);A(:,1)=Y';D=zeros(n-2,n-2);g=zeros(n-2,1);
         for  j=2:n
            for i=j:n
                A(i,j)=(A(i,j-1)- A(i-1,j-1))/(X(i)-X(i-j+1));
            end
         end
         
         for i=1:n-1
             h(i)=X(i+1)-X(i);
         end        
         for i=1:n-2
             D(i,i)=2;
             if (i==1)
                 g(i,1)=(6/(h(i+1)+h(i)))*(A(i+2,2)-A(i+1,2))-h(i)/(h(i)+h(i+1))*y0;
             elseif (i==(n-2))
                 g(i,1)=(6/(h(i+1)+h(i)))*(A(i+2,2)-A(i+1,2))-(1-h(i)/(h(i)+h(i+1)))*yn;
             else
                 g(i,1)=(6/(h(i+1)+h(i)))*(A(i+2,2)-A(i+1,2));
             end             
         end
         for i=2:n-2
             u(i)=h(i)/(h(i)+h(i+1));
             n(i-1)=h(i)/(h(i-1)+h(i));
             D(i-1,i)=n(i-1);
             D(i,i-1)=u(i);             
         end
         M=D\g;
         M=[y0;M;yn];         
end

function s=threesimple2(X,Y,x,y0,yn)
%        第二边界条件函数 
%        s函数表示三次样条插值函数插值点对应的函数值
%        根据三次样条参数函数求出的D,h,A,g,M
%        x表示求解插值点函数点,X为已知插值点        
         [D,h,A,g,M]=three2(X,Y,y0,yn)
         n=length(X); m=length(x);    
         for t=1:m
            for i=1:n-1
               if (x(t)<=X(i+1))&&(x(t)>=X(i))
                  p1=M(i,1)*(X(i+1)-x(t))^3/(6*h(i));
                  p2=M(i+1,1)*(x(t)-X(i))^3/(6*h(i));
                  p3=(A(i,1)-M(i,1)/6*(h(i))^2)*(X(i+1)-x(t))/h(i);
                  p4=(A(i+1,1)-M(i+1,1)/6*(h(i))^2)*(x(t)-X(i))/h(i);
                  s(t)=p1+p2+p3+p4; 
                  break;
               else
                   s(t)=0; 
               end
            end
         end
end

3. 分析例

  以下から選択されたトピック:『数値解析 第5版 李清陽』P49ページの問20話題は以下の通り

ここに画像の説明を挿入

1. 最初の小さな質問

  これは最初の境界値問題に属し、値を書き込み、上で書いた Matlab コードを呼び出します。

x=[0.25 0.3 0.39 0.45 0.53];
y=[0.5 0.5477 0.6245 0.6708 0.7280];
y0=1.000 ;          %  S'(x0)=f'(x0)=y0   
yn=0.6868;          %  S'(xn)=f'(xn)=yn
x0=0.25:0.01:0.53;
s=threesimple1(x,y,x0,y0,yn)
plot(x0,s)        %绘制第一边界条件插值函数图像
hold on
grid on
plot(x,y,'o')
axis([0.2 0.55 0.4 0.75])
xlabel('自变量 X'), ylabel('因变量 Y')
title('插值点与三次样条函数') 
legend('三次样条插值点坐标','插值点')

実行後の結果は次のようになります。
ここに画像の説明を挿入
ここに画像の説明を挿入

2. 2 番目の小さな質問

  これは 2 番目の境界値 (自然境界) 問題に属しており、値を書き込み、上で書いた Matlab コードを呼び出します。

x=[0.25 0.3 0.39 0.45 0.53];
y=[0.5 0.5477 0.6245 0.6708 0.7280];
y0=0;          %  S''(x0)=f''(x0)=y0   
yn=0;          %  S''(xn)=f''(xn)=yn
x0=0.25:0.01:0.53;
s=threesimple2(x,y,x0,y0,yn)
plot(x0,s)        %绘制第二边界条件插值函数图像
hold on
grid on
plot(x,y,'o')
axis([0.2 0.55 0.4 0.75])
xlabel('自变量 X'), ylabel('因变量 Y')
title('插值点与三次样条函数') 
legend('三次样条插值点坐标','插值点')

実行後の結果は次のようになります。
ここに画像の説明を挿入
ここに画像の説明を挿入

4. まとめ

  コードは似ているように見えますが、実際にはまだロジックの変更点がいくつかあり、読者にはゆっくりと理解する必要があります。これらのコードと例が、読者が数式をよりよく理解するのに役立つことを願っています。実際、C/C++ を書きたい読者の中には、主にロジックは同じですが、記述方法がいくつか異なるため、コードを真剣に検討することもできます。読者の皆様、辛抱強く読んでいただきありがとうございます。文章が良いと思われましたら、編集者に高く評価していただけますか? ありがとうございます。

5.補足

  コードを改善および最適化し、主に上記の 1 つ目と 2 つ目のメソッドを 1 つの関数にマージしてパッケージ化しました (多項式関数の出力はありません。心配しないでください。後で更新されるエルミートの違いを辛抱強く待ってください)この方法では、関数式の出力もオンラインで更新されます。関数式の出力は不完全なバージョンを作成しましたが、まだ最適化中です。緊急に必要な場合は、プライベートでチャットする必要があります) のリンクをクリックしてください。完全な情報: 最適化と完全な コード(データが完成したらアップロードします)  多くの人が式を表示する方法について質問しているため、最近コードを急遽修正しました。下の図は、不完全な表示式スキームを示しています。最初に示します。急いで書かないでください。次のエルミート差分法にご期待ください。

ここに画像の説明を挿入

6. 式を追加する

  今回の更新は(2022.5.3)、サンプルを再度変更し、あまり意味のないサンプルを直接アップロードしました(ここでの新しい関数のサンプルは最初の境界条件の下にあります)、ご覧いただきありがとうございます。

  メイン機能:

clc
clear all
format short
x=0:1:10;
y=[0.0 0.79 1.53 2.19 2.71 3.03 3.27 2.89 3.06 3.19 3.29];
y0=0.8 ;          %  S'(x0)=f'(x0)=y0   
yn=0.2;           %  S'(xn)=f'(xn)=yn
x0=0:0.01:10;
[s,s1,a]=threesimple1(x,y,x0,y0,yn)
figure
plot(x0,s)        %绘制第一边界条件插值函数图像
hold on
grid on
plot(x,y,'o')
xlabel('自变量 X'), ylabel('因变量 Y')
title('插值点与三次样条函数') 
legend('三次样条插值点坐标','插值点')
S=dispf(a)

結果 (同じ出力結果の一部はここには示されていません。コードをコピーして自分で実行してみてください):
ここに画像の説明を挿入

各区分関数の係数:
ここに画像の説明を挿入

各区分関数の形式は次のとおりです。
ここに画像の説明を挿入

针对上述1中代码更新(2022.5.3)この関数は、最初の境界条件のコード更新です ( 新增函数及功能:1. ここで係数行列の出力を増加しますa、2. 新しいdispf関数は各区分式を出力できます)。

function [D,h,A,g,M]=three1(X,Y,y0,yn)
%        自然边界条件的三次样条函数(第一种边界条件)
%        此函数为M值求值函数
%        D,h,A,g,M输出量分别为系数矩阵D,插值宽度h,差商表A,g值,M值 
         n=length(X); 
         A=zeros(n,n);A(:,1)=Y';D=zeros(n,n);g=zeros(n,1);
         for  j=2:n
            for i=j:n
                A(i,j)=(A(i,j-1)- A(i-1,j-1))/(X(i)-X(i-j+1));
            end
         end
         
         for i=1:n-1
             h(i)=X(i+1)-X(i);
         end
         for i=1:n
             D(i,i)=2; 
             D(1,2)=1;
             D(n,n-1)=1;
             if (i==1)
                 g(i,1)=6/h(i)*(A(2,2)-y0); 
             elseif (i==n) 
                     g(i,1)=6/h(i-1)*(yn-A(i,2));
             else 
                 g(i,1)=(6/(h(i-1)+h(i)))*(A(i+1,2)-A(i,2));
             end
           
         end  
         for i=1:n-2
             u(i)=h(i)/(h(i)+h(i+1));
             n(i)=1-u(i);  
             D(i+1,i+2)=n(i);
             D(i+1,i)=u(i);             %改到这里
         end
         M=D\g;
         %M=[0;M;0];         
end

function f=dispf(a)   % 输出函数表达式
    syms x;
    f=a(:,1).*x^3+a(:,2).*x^2+a(:,3).*x+a(:,4);
end

function [s,s1,a]=threesimple1(X,Y,x,y0,yn)
%        三次样条插值函数第一类型代码 
%        
%        根据三次样条参数函数求出的D,h,A,g,M
%        x表示求解插值点函数点,X为已知插值点 

% output:
%        s1表示三次样条插值函数插值点对应的函数值
%        a为分段函数各项系数矩阵
%        s为了画图生成丝滑曲线细化区间点对应的函数值
         [D,h,A,g,M]=three1(X,Y,y0,yn)
         n=length(X); m=length(x);    
         for t=1:m
            for i=1:n-1
               if (x(t)<=X(i+1))&&(x(t)>=X(i))
                  p1=M(i,1)/(6*h(i));
                  p2=M(i+1,1)/(6*h(i));
                  p3=(A(i,1)-M(i,1)/6*(h(i))^2)/h(i);
                  p4=(A(i+1,1)-M(i+1,1)/6*(h(i))^2)/h(i);
                  p(i,:)=[p1,p2,p3,p4];
                  a1=p(i,2)-p(i,1);
                  a2=3*p(i,1)*X(i+1)-3*p(i,2)*X(i);
                  a3=3*p(i,2)*(X(i))^2-3*p(i,1)*(X(i+1))^2+p(i,4)-p(i,3);
                  a4=p(i,1)*(X(i+1))^3-p(i,2)*(X(i))^3+p(i,3)*X(i+1)-p(i,4)*X(i);
                  a(i,:)=[a1,a2,a3,a4];
                  s1(i)=3*a1*(X(i))^2+2*a2*(X(i))+a3;
                  s(t)=p1*(X(i+1)-x(t))^3+p2*(x(t)-X(i))^3+p3*(X(i+1)-x(t))+p4*(x(t)-X(i)); 
                  break;
               else
                  s(t)=0; 
               end
            end
         end         
end

7. 補間列

コラムリンク:補間方法コラム、お役に立ちましたら、「いいね!」と購読していただければ、このコラムを改善していきます

  1. 数値解析(1) ニュートン補間法とMATLABコード

  2. 数値解析(2) 3次スプライン補間法matlabプログラム

  3. 数値解析(4) Hermite(ハーミット)補間法とMATLABコード

おすすめ

転載: blog.csdn.net/cugautozp/article/details/107068452