变步长梯形积分算法求解函数定积分

算法基本原理:把原区间分为一系列小期间(n份),在每个小区间上都用小的梯形面积来近似代替原函数的积分,当小区间足够小时,就可以得到原来积分的近似值。但是这个过程中有一个问题是步长的取值,步长太大精度难以保证,步长太小会导致计算量的增加,所以,实际计算中常常采用变步长的方法,使得在步长逐次减小的过程中,求得的积分结果满足要求的精度为止。

       首先,给出两个计算公式

              (1) //计算步长为h的积分

              (2) //将步长h二分,计算以h/2为步长的积分

步骤:

  • 取n=1,利用公式(1)计算积分值
  • 进行二分,利用新的公式(2)计算新的积分值
  • 进行判断,如果两次计算积分值的差在给定的误差范围之内,二分后的积分值就是所需的结果,计算结束,否则返回第二步继续运行

因此,主要计算的问题有两个

一. 被积函数值的运算(设置Function类)

二. 变步长梯形积分的实现(设置Trapz类)

#ifndef _TRAPZINT_H_
#define _TRAPZINT_H_

class Function{
public:
	virtual double operator()(double x) const = 0;//纯虚函数重载运算符()
	virtual ~Function(){}//析构函数
};

class MyFunction :public Function{
public:
	virtual double operator()(double x) const;//覆盖虚函数
};

class Integration{//抽象类Integration的定义
public:
	virtual double operator()(double a, double b, double eps) const = 0;
	virtual ~Integration(){}
};

class Trapz :public Integration{//公有派生类Trapz的定义
public:
	Trapz(const Function &f) :f(f){}//构造函数
	virtual double operator()(double a, double b, double eps) const;//覆盖虚函数
private:
	const Function &f;//私有成员,Function类对象的指针
};

#endif
#include"Trapzint.h"
#include<iostream>
#include<cmath>
using namespace std;

//计算被积函数的函数值
double MyFunction::operator()(double x) const{
	return log(1.0 + x) / (1.0 + x*x);
}

//积分运算过程,重载为运算符()
double Trapz::operator()(double a, double b, double eps) const{
	//计算区间[a,b]之间误差在eps之内的积分值
	bool done = false;//Trapz类的虚函数成员
	int n = 1;
	double h = b - a;
	double tn = h*(f(a) + f(b)) / 2;//计算n=1时的积分
	double t2n;//步长为一半的时候的积分值
	do{
		double sum = 0;
		for (int k = 0; k < n; k++){
			double x = a + (k + 0.5)*h;
			sum += f(x);
		}
		t2n = (tn + h*sum) / 2.0;//利用公式(2)计算积分
		if (fabs(tn - t2n) < eps)
			done = true;//判断积分误差
		else{
			tn = t2n;
			n *= 2;
			h /= 2;
		}
	} while (!done);
	return t2n;
}
#include"Trapzint.h"
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
	MyFunction f;//定义MyFunction类的对象
	Trapz trapz(f);//定义Trapz类的对象
	//计算并输出结果
	cout << "Trapz Int:" << setprecision(7) << trapz(0, 2, 1e-7) << endl;
	return 0;
}

结果

猜你喜欢

转载自blog.csdn.net/Dear_Jia/article/details/84923702