序文
前回の記事のリンク: 数値解析 (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. 補間列
コラムリンク:補間方法コラム、お役に立ちましたら、「いいね!」と購読していただければ、このコラムを改善していきます