c++-利用二分变步长积分算法求定积分

算法简介:p325

就是最常见的划分小区间,求单个小区间的面积,再累加。

唯一的不同就是计算机没办法控制分成的区间个数,所以我们通过设置精度的方法来控制程序二分的次数,从而简介达到划分足够大的小区间的目的。

 程序设计分析:

1.待解决的问题一:函数值的计算,求那个理想矩形面积不仅需要区间长度来近似成为矩形的宽,还需要函数值来近似成矩形的高。

2.待解决的问题二:积分的实现(实际上就是累加外加一个精度判断)

1.问题一的解决办法:设置一个求函数的类

2.问题二的解决办法:设置一个求积分的类

统筹:采取分文件编写和纯虚函数的抽象类。 设立两个类族,一个是求函数值的函数解析式的类族。一个是用来求积分但是算法不同的类族。 (这样的目的是如果有新的函数解析式,直接编写一个新的函数子类即可,如果有新的算法,也是直接编写一个积分算法子类即可,极大的增强了程序的可扩展性。) 

代码实现: 

举例:求下面这个积分

//file1.h
#ifndef _FILE1_H
#define _FILE1_H

//函数解析式类族的定义,这里只写了一个解析式的类来便于说明,实际使用的时候可以根据需要加
class function {
public:
	virtual double operator()(double x)const = 0;  //()的重载,使其具有求函数值的功能,因为平常我们不是习惯用f()来求值嘛,这样省事,你想想,如果再写写一个函数,调用的时候又得一大串,很麻烦。
	virtual ~function() {}; //虚析构,如果下面的子类涉及到堆区内存开辟,就派生用场了。
};
class my_function :public function {
public:
	double operator()(double x)const;
};

//积分求解的算法类族定义,这里也是以上面介绍的算法为例,如果有新的算法,也可以直接建一个my_intergation1等等来完成扩展。
class intergation {
public:
	virtual double operator()(double a, double b, double eps)const = 0;
	virtual ~intergation() {};
};
class my_intergation :public intergation{
	const function& f;
public:
	my_intergation(const function& f) :f(f){}
	virtual double operator()(double a, double b, double eps)const;
};
#endif 
//file1的实现
#include<iostream>
#include"file1.h"
#include<cmath>
using namespace std;
//返回带入x求解后的函数值,直接借助()的重载来实现,不用再编写一个函数来实现,极大的简化了书写的效率,很精妙的一步。
double my_function::operator()(double x)const {
	return log(1.0 + x) / (1.0 + x * x);
}

//积分算法类的实现。
double my_intergation::operator()(double a, double b, double eps)const {
	bool done = false;
	int n = 1;
	double h = b - a;
	double tn = h * (f(a) + f(b)) / 2;
	double t2n;
	do {
		double sum = 0;
		for (int i = 0; i < n; i++) {
			double x = a + (i + 0.5) * h; 
			sum += f(x);
		}
		t2n = (tn + h * sum) / 2.0;
		if (fabs(t2n - tn) < eps) {
			done = true;
		}
		else
		{
			tn = t2n;
			n *= 2;
			h /= 2;
		}
		   
	} while (!done);
	return t2n;
}
//主函数cpp
#include<iostream>
#include"file1.h"
#include<iomanip>
using namespace std;
int main() {
	my_function f;
	my_intergation trazp(f);  //注意:这里的trazp后面的()和下面的那句话里的()不一样,这个是拿f来初始化my_intergation类的对象trazp,下面那个是重载后的(),相当于调用了名字为()的函数,编译器根据参数列表来判断改用哪个,我们只需写好参数列表就行。
	cout << setprecision(8) << trazp(0, 2, 1e-7) << endl;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ad_m1n

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值