牛顿插值

最近突然被要求实现光滑曲线……看看也就牛顿插值比较好理解了

牛顿插值法(就不科普了)http://wenku.baidu.com/view/8527ad1da300a6c30c229f54.html

Point2:用来存储键值对的  x,f(x)

caculate(): 是根据均差的定义暴力求解的(一次性求取一组点的均差列表)

caculate2():模拟实现那个三角形的求解方法(逐个添加点的时候求取均差)

caculate3():模拟实现那个三角形的求解方法(一次性求取一组点的均差列表)

val(x,```)求取在x处函数的值f(x)  通过之前求解的均差列表


在这边编辑文本好艰难的样子……在编译器里面的格式全部丢失了……

比较详细的参见 http://www.oschina.net/code/snippet_129941_18465

#include <cstdlib>
#include <iostream>
#include <vector>
#include <windows.h>
//#include <>
using namespace std;


class Point2
{
public:
    float valX;
    float valY;
public:
    Point2(void):valX(0.0f), valY(0.0f)
    {}
    Point2(float valX, float valY):valX(valX), valY(valY)
    {}
    ~Point2()
    {}
};
/*
** 求 x 点处 的插值 f(x) 
**poArray 为[xi,f(xi)] 列表, avxArray 为均差列表 f[x0,x1,.....xn] 
** return f(x)
*/
float val(float x, vector<Point2> &poArray, vector<float> &avxArray)
{
    float px = poArray.at(0).valY;//f(x)
    float mulx = 1.0f;//(x-x0)(x-x1)....
    //f(x) = f(x0)+f[x0,x1](x-x0)+...+f[x0,x1,...,xn](x-x0)(x-x1)...(x-xn-1)
    for(size_t i = 0; i < poArray.size()-1; ++i)
{
mulx *= x-poArray.at(i).valX;
px += avxArray.at(i)*mulx;
}


cout << x <<"  "<<px << endl;
return px;
}
/*
** 根据定义求均差 
**poArray 为[xi,f(xi)] 列表; avxArray 为均差列表 f[x0,x1,.....xn] 
** 
*/
void caculate( vector<Point2> &poArray, vector<float>& avxArray)
{
avxArray.clear();
// avxArray.reserve(poArray.size()-1);


// vector<Point2> poArray;
// vector<float> avxArray;
// poArray.push_back(Point2(1.0f, 2.4f));
// poArray.push_back(Point2(3.0f, 3.5f));
// poArray.push_back(Point2(4.0f, 20.0f));
// poArray.push_back(Point2(6.0f, 18.0f));
// poArray.push_back(Point2(7.0f, 1.8f));
// poArray.push_back(Point2(8.0f, 2.4f));
// poArray.push_back(Point2(9.0f, 1.8f));


// for(size_t i = 0; i < poArray.size(); ++i)
// {
// cout<<poArray.at(i).valX <<"  "<<poArray.at(i).valY<<endl;
// }
float fxj = 0.0f; //f(xj)
float xj = 0.0f;  // xj
float mulx = 1.0f; //(xj-x0)(xj-x1).....
float addAvg = 0.0f;//f[x0, x1, x2, xk....] 
for(size_t k = 1, j = 0, i = 0; k < poArray.size(); ++k)
{
addAvg = 0.0f;
for(j = 0; j <= k; ++j)
{
fxj = poArray.at(j).valY;
mulx = 1.0f;
xj = poArray.at(j).valX;
for(i = 0; i <= k; ++i)
{
if(i == j) continue;
mulx *= (xj-poArray.at(i).valX);
}
addAvg += fxj/mulx;

}
avxArray.push_back(addAvg);
}
// cout<<"^^^^^^^^^^^^caclute^^^^^^^"<<endl;
// for(size_t i = 0; i < avxArray.size(); ++i)
// {
// //cout<<poArray.at(i).valX <<"  "<<poArray.at(i).valY<<endl;
// cout << i << "    " << avxArray.at(i) << endl;
// }
//
// cout << "the  value" <<endl;
//
// float myx = 0.0f;
// for(int i = 0; i < 10; ++i) 
// for(int j = 0; j < 10; ++j)
// {
//
// val(i+j*0.1f, poArray, avxArray);
// }

}


/*
**根据那个三角形计算方法地推
**(速度比较快) 
**poArray的最后一个点是新加入的点,即待计算的点 
**即动态添加节点(比较常用,也比较符合实际应用) 
**avxArray 为均差列表 
**avxArray_B 牛顿插值三角形底边的均差值列表 
** 即:f[xn-1,xn] 、f[xn-2,xn-1,xn]....f[x0,x1,x2....xn] 
** 
*/
void caculate2(vector<Point2> &poArray,
vector<float> &avxArray,vector<float> &avxArray_B)
{
// cout<<poArray.size()<<"  "<<avxArray.size()<<"  "<<avxArray.size()<<endl;
if(poArray.size()<2) return ;//至少要两个点好不……
// Point2& lastPo = poArray.back(); //待计算的点  
float oldAvx = 0.0f,//就的均差值
 newAvx = 0.0f; //x新的均差值 
unsigned int povSize = poArray.size(), //点的个数 
// tempSize = povSize - 2,
idx = 0, //
avxSize = avxArray.size(); //均差的个数=三角底边的个数 

//f[xn-1, xn]  
newAvx = (poArray.back().valY - poArray.at(povSize-2).valY)
                   /(poArray.back().valX - poArray.at(povSize-2).valX);
// if(avxSize> 0) avxArray_B.at(0) = newAvx;
for(idx = 0; idx < avxSize; ++idx)
{//替换原有三角最底边的 值 //相当于新添加一条底边 
// system("PAUSE");
oldAvx = avxArray_B.at(idx);
avxArray_B.at(idx) = newAvx;
newAvx = (newAvx - oldAvx)
/(poArray.at(povSize-1).valX -poArray.at(povSize-3-idx).valX );

}


//添加新元素 
avxArray.push_back(newAvx);
avxArray_B.push_back(newAvx);  
}


/*
**根据那个三角形计算方法地推
**(速度比较快) 
**求整个poArray里面的点,相当于其他两个数组里面的列表为空 
**即动态添加节点(比较常用,也比较符合实际应用) 
**avxArray 为均差列表 
**avxArray_B 牛顿插值三角形底边的均差值列表 
** 即:f[xn-1,xn] 、f[xn-2,xn-1,xn]....f[x0,x1,x2....xn] 
** 
*/
void caculate3(vector<Point2> &poArray,
vector<float> &avxArray,vector<float> &avxArray_B)
{
avxArray.clear();
avxArray_B.clear();
// avxArray.reserve(poArray.size()-1);
// avxArray_B.reserve(poArray.size()-1);
if(poArray.size()<2) return ;//至少要两个点好不……
// Point2& lastPo = poArray.back(); //待计算的点  
float oldAvx = 0.0f,//就的均差值
 newAvx = 0.0f; //x新的均差值 
unsigned int povSize = poArray.size(), //点的个数 
// tempSize = povSize - 2,
idx1 = 0, //
idx2 = 0,
avxSize = avxArray.size(); //均差的个数=三角底边的个数 

//f[xn-1, xn]  
// newAvx = (poArray.back().valY - poArray.at(povSize-2).valY)
//              /(poArray.back().valX - poArray.at(povSize-2).valX);
for(idx1 = 1; idx1<povSize; ++idx1)
{
newAvx = (poArray.at(idx1).valY - poArray.at(idx1-1).valY)
           /(poArray.at(idx1).valX - poArray.at(idx1-1).valX);
for(idx2 = 0; idx2 <avxSize; ++idx2)
{//替换原有三角最底边的 值 //相当于新添加一条底边 
// system("PAUSE");
oldAvx = avxArray_B.at(idx2);
avxArray_B.at(idx2) = newAvx;
newAvx = (newAvx - oldAvx)
/(poArray.at(idx1).valX -poArray.at(idx1-2-idx2).valX );
}
//添加新元素 
avxArray.push_back(newAvx);
avxArray_B.push_back(newAvx);
avxSize = avxArray.size();
// for(idx1 = 0; idx1 < avxArray.size(); ++idx1)
// cout<<avxArray.at(idx1)<<endl;
// cout<<"------------------------\n"<<endl;
}

}
int main(int argc, char *argv[])
{


vector<Point2> poArray;//[x,f(x)] 列表 
vector<float> avxArray;//f[x0,x1,x2....xn] 均差列表
vector<float> avxArray_B; //牛顿插值三角形底边的均差值列表 
//即:f[xn-1,xn] 、f[xn-2,xn-1,xn]....f[x0,x1,x2....xn] 
DWORD oldTime, newTime;
size_t mySize = 1000;
poArray.reserve(mySize);
avxArray.reserve(mySize-1);
avxArray.reserve(mySize-1);
/* poArray.push_back(Point2(1.0f, 2.4f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(3.0f, 3.5f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(4.0f, 20.0f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(6.0f, 18.0f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(7.0f, 1.8f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(8.0f, 2.4f));
caculate2(poArray, avxArray, avxArray_B);
poArray.push_back(Point2(9.0f, 1.8f));
caculate2(poArray, avxArray, avxArray_B);
*/
srand(GetTickCount());
cout<<"*********caculate2***********"<<endl;
oldTime = GetTickCount();
for(int i = 0; i < mySize; ++i)
{
poArray.push_back(Point2(1.0f*i, rand()%500));
caculate2(poArray, avxArray, avxArray_B);
}
newTime = GetTickCount();
cout<<oldTime<<" ~ "<<newTime<<  "    spend(ms): "<<(newTime-oldTime)<<endl;
// avxArray.clear();

for(size_t i = 0; i < avxArray.size(); ++i)
{
//cout<<poArray.at(i).valX <<"  "<<poArray.at(i).valY<<endl;
// cout << i << "    " << avxArray.at(i) << endl;
}
cout<<"\n*********caculate***********"<<endl;
poArray.clear();
oldTime = GetTickCount();
for(int i = 0; i < mySize; ++i)
{
poArray.push_back(Point2(1.0f*i, rand()%500));


}
caculate(poArray, avxArray);
newTime = GetTickCount();
cout<<oldTime<<" ~ "<<newTime<<  "    spend(ms): "<<(newTime-oldTime)<<endl;

for(size_t i = 0; i < avxArray.size(); ++i)
{
//cout<<poArray.at(i).valX <<"  "<<poArray.at(i).valY<<endl;
// cout << i << "    " << avxArray.at(i) << endl;
}
// system("PAUSE");
cout<<"\n*********caculate3***********"<<endl;
poArray.clear();
oldTime = GetTickCount();
for(int i = 0; i < mySize; ++i)
{
poArray.push_back(Point2(1.0f*i, rand()%500));
}
caculate3(poArray, avxArray, avxArray_B);
newTime = GetTickCount();
cout<<oldTime<<" ~ "<<newTime<<  "    spend(ms): "<<(newTime-oldTime)<<endl;

for(size_t i = 0; i < avxArray.size(); ++i)
{
//cout<<poArray.at(i).valX <<"  "<<poArray.at(i).valY<<endl;
// cout << i << "    " << avxArray.at(i) << endl;
}
// cout<<sizeof(Point2)<<endl;
//    system("PAUSE");
// memApply();
    system("PAUSE");
    return EXIT_SUCCESS;
}


转载于:https://my.oschina.net/ccyuan/blog/109378

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值