现在的位置: 首页 > 综合 > 正文

使用虚拟容器的方法实现梯形公式的逐次分半法求积分(2)

2013年02月18日 ⁄ 综合 ⁄ 共 2717字 ⁄ 字号 评论关闭
#include <iostream>
#include <iterator>
#include <algorithm>
#include <functional>
#include <cmath>
#include "dummy.h"
template< class Function > struct Method
{
typedef std::pair<double,double> element_type;
struct Generator:std::unary_function<const size_t&,element_type&>
{
element_type&operator()(const size_t&i)
{
Function f;
const double&a=Method::range().first;//积分下限
const double&b=Method::range().second;//积分上限
double&Tn = Method::value().first;//上一次的分办法的梯形法积分结果
double&T2n= Method::value().second;//这一次分半之后的梯形法积分结果
if(i==0||i==1){//第一次执行的时候才会执行下面的代码
Tn = (b-a)/2*(f(a)+f(b));
T2n = Tn/2+(b-a)/2*f((a+b)/2);
}else{
const size_t n = i+1;
Tn = T2n;//保存上一次的积分结果
T2n = 0;//将这个变量用来存储临时结果
size_t j; for(j=1;j<=n;j++) T2n += f(a+(2*j-1)*(b-a)/2/n);
T2n = Tn/2+(b-a)/2/n*T2n;//该变量用来保存最后的积分结果
}
return Method::value();
}
};
//积分的循环终止条件
struct Predicate:std::unary_function<const element_type&,bool>
{
Predicate(const double&eps):_eps(eps){}
bool operator()(const element_type&e)
{
return fabs( e.first - e.second ) < 3 * _eps;
}
private:
Predicate(){}
double _eps;
};
public:
//这个静态函数用来设置积分的上限值和下限值
static void range(const double&a,const double&b)
{
range() = std::make_pair(a,b);
}
private:
//这个静态函数用来保存积分上限和积分下限值
static element_type&range()
{
static element_type _value;
return _value;
}
//这个静态函数用来保存前一次积分值和再次分半之后的积分值
static element_type&value()
{
static element_type _value;
return _value;
}
};
//下面的这个仿函数就是我们将要进行积分的函数
struct Function:std::unary_function<const double&,double>
{
double operator()(const double&x)
{
return sin(x);
}
};
//在这里实现了方法和被积函数的分离,而且充分利用了STL已有的算法,避免了这些重复代码
//因而代码可读性增加。这也是使用虚拟容器的目的所在!
int main()
{
std::cout.precision(20);
typedef Method<Function> M;
typedef dummy<M::element_type,M::Generator> INTEGRAL;
const double PI = 3.1415926535897932384626433832795;
{
M::range(0.0,PI/2.0);//设置积分区间
INTEGRAL v(0,10000);//为了避免死循环给出了最大的循环次数
INTEGRAL::iterator result = std::find_if(v.begin(),v.end(),M::Predicate(1e-5));
std::cout << "迭代次数:[" << static_cast<const size_t&>(result) << "]" << std::endl;
std::cout << "左积分:[" << (*result).first << "]" << std::endl;
std::cout << "右积分:[" << (*result).second << "]" << std::endl;
}
{
M::range(-PI/2.0,0.0);//设置积分区间
INTEGRAL v(0,10000);//为了避免死循环给出了最大的循环次数
INTEGRAL::iterator result = std::find_if(v.begin(),v.end(),M::Predicate(1e-5));
std::cout << "迭代次数:[" << static_cast<const size_t&>(result) << "]" << std::endl;
std::cout << "左积分:[" << (*result).first << "]" << std::endl;
std::cout << "右积分:[" << (*result).second << "]" << std::endl;
}
return 0;
}
////////////////////////////////////////////////////////////////////////////////
//运行结果如下:
/*******************************************************************************
迭代次数:[20]
左积分:[1.0002621998308148]
右积分:[1.0002404226766435]
迭代次数:[20]
左积分:[-1.0002621998308148]
右积分:[-1.0002404226766435]
*******************************************************************************/
////////////////////////////////////////////////////////////////////////////////

抱歉!评论已关闭.