n個の異なる点での関数値
が与えられたとき、
これら全ての点を通る曲線の方程式を求め
その方程式から任意のxに対する関数値を近似する方法を補間という。
簡単化のため視点Oを省略する。
線形補間とは、tを0から1までに動かしたときのQの値を求めることで、
P0からP1までの間の点を補ってやることである。
○プログラム例
Point linerInterpolation(double t) { point.x=(int)(x0*(1.0-t) + x1*t); point.y=(int)(y0*(1.0-t) + y1*t); return point; }
関数形が分からないが、
独立変数xの離散値と
従属変数yの離散値から、
関数の概形を決定する方法として、
ニュートンの補間法がある。
は、n階の前進差分を示す。
ゆえに、
(式1-2)
ここで二項定理
一般の二項定理
を使うと、
(式1-3)
ここで、ある任意の点と、
点
の関係は、図を見ると明らかなように、
(例
例えば s=4のときのが分かっているとき、
は?
となる。)
この関係は、
となり、
このs,s-1,s-2を式(1-3)に代入すると、ニュートンの補間式を得る。
/*************************************************************/ /* Newton の補間公式 */ /* written by embedded.samurai */ /*************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> double i[]={ -1.122182, 0.841471, 0.539353, 0.0, 0.779067, 2.524414, 3.366545}; double dif[6][7]; int main(void) { int n=0; int m=0; double e=0.; double s=0.; double g2=0.,g4=0.,g6=0.; FILE *fout; //file open fout = fopen("output.txt","w"); // 0 initial memset(dif,0,sizeof(dif)); //1階差分 for(n=0;n<6;n++){ dif[0][n] = i[n+1]-i[n]; } //2階差分 for(n=0;n<5;n++){ dif[1][n] = dif[0][n+1] - dif[0][n]; } //3階差分 for(n=0;n<4;n++){ dif[2][n] = dif[1][n+1] - dif[1][n]; } //4階差分 for(n=0;n<3;n++){ dif[3][n] = dif[2][n+1] - dif[2][n]; } //5階差分 for(n=0;n<2;n++){ dif[4][n] = dif[3][n+1] - dif[3][n]; } //6階差分 for(n=0;n<1;n++){ dif[5][n] = dif[4][n+1] - dif[4][n]; } e=-1.5; //出力 printf("y=E[V] x=I(mA) dy d^2y d^3y d^4y d^5y d^6y\n"); for(n=0;n<7;n++){ printf("%+3.1f\t%+7.5f ",e,i[n]); for(m=0;m<6;m++){ printf("%+7.5f ",dif[m][n]); } printf("\n"); e=e+0.5; } //ニュートンの前進差分補間公式 for(e=-1.5;e<1.6;e=e+0.1){ s=2.0*e + 3.0; //(x-(-1.5))/0.5 s=(x-x_0)/h //2階差分 g2 = i[0] + s*dif[0][0] + s*(s-1)*dif[1][0]/2.; //4階差分 g4 = i[0] + s*dif[0][0] + s*(s-1)*dif[1][0]/2. + s*(s-1)*(s-2)*dif[2][0]/6. + s*(s-1)*(s-2)*(s-3)*dif[3][0]/24.; //6階差分 g6 = i[0] + s*dif[0][0] + s*(s-1)*dif[1][0]/2. + s*(s-1)*(s-2)*dif[2][0]/6. + s*(s-1)*(s-2)*(s-3)*dif[3][0]/24. + s*(s-1)*(s-2)*(s-3)*(s-4)*dif[4][0]/120. + s*(s-1)*(s-2)*(s-3)*(s-4)*(s-5)*dif[5][0]/720. ; fprintf(fout,"%e %e %e %e\n",e,g2,g4,g6); } fclose(fout); return 0; }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % newton interpolation's graph % written by embedded.samurai %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% echo on close all clear all figure(1) load('output.txt'); xdata=[-1.5 -1.0 -0.5 0.0 0.5 1.0 1.5]; xdata=xdata'; ydata=[-1.122182 0.841471 0.539353 0.0000 0.779067 2.524414 3.366545]; ydata=ydata'; data=cat(2,xdata,ydata); plot(data(:,1),data(:,2),'ro','linewidth',2) %semilogx(output(:,1),output(:,2),'ro-','linewidth',2) hold on plot(output(:,1),output(:,2),'b-','linewidth',2) hold on plot(output(:,1),output(:,3),'g-','linewidth',2) hold on plot(output(:,1),output(:,4),'m-','linewidth',2) grid on xlabel('電圧[V]','Fontsize',18) ylabel('電流[mA]','Fontsize',18) h=legend('測定データ',..., '2階差分',..., '4階差分',..., '6階差分',..., 1); set(h,'FontSize',15) h=gca set(h,'LineWidth',2,..., 'FontSize',18) %axis([-Inf Inf -Inf Inf]); axis([ -1.5 1.5 -2 4 ]); print -djpeg newton_graph.jpeg