📄 曲线拟合2.txt
字号:
已知美国从1920-1970年的人口表如下:
年份 1920 1930 1940 1950 1960 1970
人口(千人) 105711 123203 131669 150697 179323 203212
(1)用表中数据构造一个5次Lagrange插值多项式,并以此估计1965、2002年的人口。
(2)用Newton插值估算1965、2002年的人口数。
插值的基本方法:根据一个给定的函数f(x)[f(x)是一个表达式很复杂,甚至写不出来的实函数]的函数值表,构造一个简单的函数g(x),使得f(xk)=g(xk)
Langrange插值方法的基本思想:f(x)在[a,b]上具有n+1阶连续导数,有n+1个插值节点满足a≤x0 ≤ x1 ≤…… ≤xn ≤b,Pn(x)是 f (x) 的n次 Lagrange插值多项式,已知y=f(x)的n+1个互异节点的值yi=f(xi) (i=0,1,2,…,n),n次多项式pn(x) =a0+a1x+a2x2+…+anxn ,满足插值条件yi=pn(xi) 用构造基函数法,构造n+1个n次多项式(基函数)且连续函数p(x)能用基函数线性表出。
Newton插值的基本方法:构造一个具有承袭性的newton插值公式:Nn(x)=c0+c1(x-x0)+c2(x-x0)(x-x1)+…+cn(x-x0)(x-x1)…(x-xn-1)并且要满足插值条件:Nn(x)=f(xi)可得到一个线性方程组,得出Newton插值公式:Nn(x)=f(x0)+f[x0,x1](x-x0)+f[x0,x1,x2](x-x0)(x-x1)+…+f[x0,x1,…xn](x-x0)(x-x1)…(x-xn-1)
Newton插值多项式为:
Nn(x)=f(x0)+f[x0,x1](x-x0)+f[x0,x1,x2](x-x0)(x-x1)+…+ f[x0,x1,…xn](x-x0)(x-x1)…(x-xn-1)
最后利用Newton插值多项式估算未知点处的函数值。
(1)#include<iostream.h>
#include<iomanip.h>
#define MN 6
double X[]={1920,1930,1940,1950,1960,1970};
double Y[]={105711,123203,131669,150697,179323,203212};//观察值
double LB[MN],LT[MN],SUMLB=0,SUMLT=0;//f0存放基函数值 ,f1存放多项式各项的值LT[K]=Y[K]*LB[K]
double X0=1965; //X0=2002;
void f0() //计算基函数值
{
cout<<"LB[K]"<<'\t';
for(int i=0;i<MN;i++)
{
LB[i]=1;
for(int j=0;j<MN;j++)
{
if(i==j)
continue;
LB[i]=LB[i]*(X0-X[j])/(X[i]-X[j]);
}
SUMLB+=LB[i];
cout<<setw(15)<<LB[i];
}
cout<<'\n';
}
void f1()
{
cout<<"LT[K]"<<'\t';
for(int i=0;i<MN;i++)
{
LT[i]=LB[i]*Y[i];
SUMLT+=LT[i];
cout<<setw(15)<<LT[i];
}
cout<<'\n';
}
void main()
{
cout.setf(ios::left);
cout<<'\n'<<"Lagrange插值方法:"<<'\n';
cout<<'k'<<'\t';
for(int i=0;i<MN;i++)
cout<<setw(15)<<i;
cout<<'\n';
for(i=0;i<MN;i++)
cout<<setw(15)<<"---------------";
cout<<'\n'<<"X[k]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<X[i];
cout<<'\n'<<"Y[k]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<Y[i];
cout<<'\n';
f0();
f1();
for(i=0;i<MN;i++)
cout<<setw(15)<<"---------------";
cout<<'\n'<<'\n'<<" "<<"X0="<<X0;
cout<<'\n'<<" "<<"SUMLB="<<SUMLB<<'\n';
cout<<" "<<"SUMLT="<<SUMLT<<'\n';
cout<<setw(15)<<"----------------"<<'\n';
}
(2)#include<iostream.h>
#include<iomanip.h>
#define MN 6
double X[]={1920,1930,1940,1950,1960,1970},Y[]={105711,123203,131669,150697,179323,203212};
double DQT[MN][MN],NT[MN],SUMNT=0; //DQT保存差商 NT保存差值多项式各项的值
double X0=1965; //X0=2002;
void f0() //求差商函数
{
double temp;
for(int i=0;i<MN;i++)
DQT[0][i]=Y[i];
for(i=0;i<MN;i++)
{
for(int j=0;j<MN;j++)
{
if(j<=i)
{
DQT[i+1][j]=0;
continue;
}
temp=DQT[i][j]-DQT[i][i];
DQT[i+1][j]=temp/(X[j]-X[i]);
}
cout<<"Q["<<i<<"]"<<'\t';
for(j=0;j<MN;j++)
{
cout<<setw(15)<<DQT[i][j];
}
cout<<'\n';
}
}
void f1() //牛顿插值函数
{
double temp;
cout<<'\n'<<"NB[K]"<<'\t';
for(int i=0;i<MN;i++)
{
temp=1;
for(int j=0;j<i;j++)
temp*=(X0-X[j]); //计算基函数∏(x)
cout<<setw(15)<<temp;
NT[i]=DQT[i][i]*temp;
SUMNT+=NT[i];
}
cout<<'\n'<<"NT[K]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<NT[i];
cout<<'\n';
}
void main()
{
cout.setf(ios::left);
cout<<"Newton插值方法:"<<'\n'<<"差商表:"<<'\n';
for(int i=0;i<MN;i++)
cout<<setw(15)<<"----------------";
cout<<'\n'<<"K"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<i;
cout<<'\n';
for(i=0;i<MN;i++)
cout<<setw(15)<<"----------------";
cout<<'\n'<<"X[K]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<X[i];
cout<<'\n';
f0();
for(i=0;i<MN;i++)
cout<<setw(15)<<"----------------";
cout<<'\n';
cout<<"X[K]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<X[i];
cout<<'\n';
cout<<"Y[K]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<Y[i];
cout<<'\n';
cout<<"F[K]"<<'\t';
for(i=0;i<MN;i++)
cout<<setw(15)<<DQT[i][i];
f1();
for(i=0;i<MN;i++)
cout<<setw(15)<<"----------------";
cout<<'\n';
cout<<'\n'<<" X0="<<X0<<'\n';
cout<<" Y0="<<SUMNT<<'\n';
cout<<setw(15)<<"----------------";
cout<<'\n';
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -