三次样条插值算法C++实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

三次样条插值算法C++实现
三次样条插值算法
1 总体说明
三次样条插值算法是⼀种计算量和效果都⽐较理想的插值算法。

关于三次样条插值算法的原理这⾥不做过多的解释,下⾯的代码是我在⽹上收集了两种C++实现版本的基础上⾃⼰整合的⼀个版本。

由于本⼈刚接触C++不久,⽔平有限。

没有使⽤模板机制将代码做的更通⽤。

关于算法实现有下⾯⼏点说明。

1. 所有有关的类都被包含到SplineSpace命名空间中。

2. SplineSpace中⼀个有三个类分别是异常类(SplineFailure),接⼝类(SplineInterface)和实现类(Spline)。

有⼀个枚举类型说明边界条件
(BoundaryCondition),取值为:GivenFirstOrder和GivenSecondOrder。

分别对应I型边界条件和II型边界条件。

3. 接⼝类定义了Spline在实现的过程中必须要有的三个⽅法:单点插值、多点插值和⾃动⽣成插值序列。

4. 异常类是可能被实现类抛出的类,如果在实现类的运⾏过程中出现了已知数据过少构造失败、使⽤了外插值、设定输出点数过少等⾏
为会抛出该类。

因此应该将插值的过程⽤try...catch(SplineFailure sf)包裹起来。

如:
double x0[2]={1,2};
double y0[2]={3,4};
try
{
SplineInterface* sp = new Spline(x0,y0,2);
//...
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
上⾯代码就会抛出异常并显⽰“构造失败,已知点数过少”。

2 插值⽅法调⽤
2.1单点插值
调⽤⽅法如下:
#include <iostream>
#include "Spline.h"
using namespace std;
using namespace SplineSpace;
int main(void)
{
//单点插值测试
double x0[5]={1,2,4,5,6}; //已知的数据点
double y0[5]={1,3,4,2,5};
try
{
//Spline sp(x0,y0,5,GivenSecondOrder,0,0);
SplineInterface* sp = new Spline(x0,y0,5); //使⽤接⼝,且使⽤默认边界条件
double x=4.5;
double y;
sp->SinglePointInterp(x,y); //求x的插值结果y
cout<<"x="<<x<<"时的插值结果为:"<<y<<endl;
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停
}
此时屏幕会输出"x=4.5时的插值结果为2.71107"。

1. 可以直接构造Spline对象进⾏使⽤,也可以将它转化成对应的接⼝使⽤。

2. 默认边界条件为II型边界条件(已知边界的⼆阶导数),默认左右边界⼆阶导数为都0,即⾃然边界条件。

3. 已知的数据点数要⾄少为3(3个点对应⼀条曲线)。

2.2多点插值
调⽤⽅法如下(省略了和上⾯重复的代码部分):
//多点插值测试
double x0[5]={1,2,4,5,6}; //已知的数据点
double y0[5]={1,3,4,2,5};
double x[4] = {1.5,2.5,3.5,4.5}; //插值点
double y[4];
double leftBound=0,RightBound=0; //边界导数
try
{
Spline sp(x0,y0,5,GivenSecondOrder,leftBound,RightBound);
sp.MultiPointInterp(x,4,y); //求x的插值结果y
for(int i = 0;i < 4;i++)
{
cout<<"x="<<x[i]<<"时的插值结果为:"<<y[i]<<endl;
}
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停
显⽰结果如下:
x=1.5时的插值结果为:2.01383
x=2.5时的插值结果为:3.8978
x=3.5时的插值结果为:4.62372
x=4.5时的插值结果为:2.71107
2.3⾃动⽣成插值序列
⾃动⽣成插值序列⽅法会根据指定的插值点数,在插值⾃变量区间等间距的⽣成插值点。

这个⽅法在绘图的时候⾮常好⽤。

指定的插值点数越多,绘制出来的图形质量越好。

调⽤⽅法如下:
//⾃动插值测试
double x0[5]={1,2,4,5,6}; //已知的数据点
double y0[5]={1,3,4,2,5};
double x[10]; //插值点
double y[10];
try
{
SplineInterface* sp = new Spline(x0,y0,5); //使⽤接⼝,且使⽤默认边界条件
sp->AutoInterp(10,x,y); //求x的插值结果y
for(int i = 0;i < 10;i++)
cout<<x[i]<<",";
cout<<endl;
for(int i = 0;i < 10;i++)
cout<<y[i]<<",";
}
catch(SplineFailure sf)
{
cout<<sf.GetMessage()<<endl;
}
getchar(); //程序暂停
显⽰结果如下:
1,1.55556,2.11111,2.66667,3.22222,3.77778,4.33333,4.88889,5.44444,6,
1,2.12528,3.21225,4.14572,4.639,4.38218,3.1524,2.02937,2.79183,5,
将上⾯结果复制粘贴到matlab中绘图,并且和matlab中的三次样条拟合结果作⽐较。

matlab代码如下: clear
clc
x0=[1,2,4,5,6]; %已知的⾃变量
y0=[1,3,4,2,5]; %已知的因变量
pp=csape(x0,y0,'second',[0,0]); %⼆阶边界条件,且导数都为0
x = linspace(1,6,200);
y = ppval(pp,x);
%C++算法得出了的结果
xCpp = [1,1.55556,2.11111,2.66667,3.22222,3.77778,4.33333,4.88889,5.44444,6];
yCpp = [1,2.12528,3.21225,4.14572,4.639,4.38218,3.1524,2.02937,2.79183,5];
h=figure;
plot(xCpp,yCpp,'*',x,y);
legend('c++插值结果','matlab插值结果')
title('插值结果')
= '插值结果';
h.NumberTitle = 'off';
结果如下:
可以看到C++中的算法得到的结果和matlab中得到的结果相同。

C++源程序代码:
下载源码:。

相关文档
最新文档