# include<iostream>
using namespace std;
float function(float x){ //被积函数
return 4.0/(1+x*x);
};
class inte_algo{ //定积分基类
protected:
float a,b; //积分区间
int n; //积分区间的等分数
float h,sum; //步长和积分值
public:
inte_algo(float left,float right,int steps){//构造函数
a=left;
b=right;
n=steps;
h=(b-a)/n;
sum=0.0;
};
virtual void integrate(void);//求定积分的虚函数,可设计为纯虚函数
};
class rectangle:public inte_algo{//矩形法积分类
public:
rectangle(float left,float right,int steps):inte_algo(left,right,steps){};
void integrate(void);
};
class ladder:public inte_algo{//梯形法积分类
public:
ladder(float left,float right,int steps):inte_algo(left,right,steps){};
void integrate(void);
};
class simpson:public inte_algo{//辛普逊法积分类
public:
simpson(float left,float right,int steps):inte_algo(left,right,steps){ };
void integrate(void);
};
void inte_algo::integrate(void){//若在基类中设计为纯虚函数,则这段代码应删除
cout<<sum<<endl;
}
void rectangle::integrate(void){
float a1=a;
for(int i=0;i<n;i++){
sum+=function(a1);
a1+=h;
}
sum *=h; //sum=(f(a)+f(a+h)+f(a+2h)+...+f(a+(n-1)*h))*h
cout<<sum<<endl;
}
void ladder::integrate(void){
float a1=a;
sum=(function(a)+function(b))/2.0;
for(int i=1;i<n;i++){
a1+=h;
sum+=function(a1);
}
sum*=h; //sum=(f(a)+2f(a+h)+2f(a+2h)+...+2f(a+(n-1)h)+f(b))h/2
cout<<sum<<endl;
}
void simpson::integrate(void){
sum=function(a)+function(b);
float s=1.0,a1=a;
for(int i=1;i<n;i++){
a1+=h;
sum+=(3.0+s)*function(a1); //系数4,2交替,使用3±1实现
s=-s;
}
sum*=h/=3.0; //sum=(f(a)+4f(a+h)+2f(a+2h)+4f(a+3h)+2f(a+4h)+...+2f(a+(n-2)h+4f(a+(n-1)h)+f(b))h/3
cout<<sum<<endl;
}
void main(void){
rectangle rec(0.0,1.0,10);
ladder lad(0.0,1.0,10);
simpson sim(0.0,1.0,10);
inte_algo *p1=&rec, *p2=&lad, *p3=∼//使用基类指针指向各派生类
p1->integrate();
p2->integrate();
p3->integrate();//虚函数的作用可体现出来,调用的分别是各派生类的虚函数
}
可以将被积函数作为参数传入定积分基类的构造函数中,同时将积分区间和等分数也作为参数传入,这样就可以实现对任意被积函数进行数值积分的运算。具体实现如下:
#include<iostream>
#include<functional> //使用函数对象需要包含的头文件
using namespace std;
class inte_algo{ //定积分基类
protected:
float a,b; //积分区间
int n; //积分区间的等分数
float h,sum; //步长和积分值
public:
inte_algo(float left,float right,int steps,function<float(float)> f){//构造函数
a=left;
b=right;
n=steps;
h=(b-a)/n;
sum=0.0;
for(int i=0;i<n;i++){
sum+=f(a+i*h);
}
sum *=h;
};
virtual void integrate(void){//求定积分的虚函数,可设计为纯虚函数
cout<<sum<<endl;
};
};
class rectangle:public inte_algo{//矩形法积分类
public:
rectangle(float left,float right,int steps,function<float(float)> f):inte_algo(left,right,steps,f){};
void integrate(void);
};
class ladder:public inte_algo{//梯形法积分类
public:
ladder(float left,float right,int steps,function<float(float)> f):inte_algo(left,right,steps,f){};
void integrate(void);
};
class simpson:public inte_algo{//辛普逊法积分类
public:
simpson(float left,float right,int steps,function<float(float)> f):inte_algo(left,right,steps,f){ };
void integrate(void);
};
void rectangle::integrate(void){
sum=0.0;
for(int i=0;i<n;i++){
sum+=function(a+i*h);
}
sum *=h;
cout<<sum<<endl;
}
void ladder::integrate(void){
sum=(function(a)+function(b))/2.0;
for(int i=1;i<n;i++){
sum+=function(a+i*h);
}
sum*=h;
cout<<sum<<endl;
}
void simpson::integrate(void){
sum=function(a)+function(b);
float s=1.0;
for(int i=1;i<n;i++){
sum+=(3.0+s)*function(a+i*h); //系数4,2交替,使用3±1实现
s=-s;
}
sum*=h/=3.0;
cout<<sum<<endl;
}
int main(void){
function<float(float)> f=[](float x){return 4.0/(1+x*x);}; //定义被积函数
rectangle rec(0.0,1.0,10,f);
ladder lad(0.0,1.0,10,f);
simpson sim(0.0,1.0,10,f);
inte_algo *p1=&rec, *p2=&lad, *p3=∼//使用基类指针指向各派生类
p1->integrate();
p2->integrate();
p3->integrate();
return 0;
}
在这个程序中,我们使用了C++11中的函数对象std::function
,它可以将一个函数或者一个函数对象作为参数传递给另一个函数或者类的构造函数。在这个例子中,我们定义了一个lambda表达式作为被积函数,然后将它作为参数传递给了定积分基类的构造函数。这样,我们就可以使用任意的被积函数进行数值积分的运算了。
位选,选位置。我要选择哪一位数码管亮。
段选,选一段。我要选择哪一段LED亮.
我建议你使用数值积分的常规方法,例如梯形法或辛普森法,这些方法可以对任意函数进行数值积分,而不需要知道函数的具体形式。具体步骤如下:
将积分区间[a,b]等分成n个小区间,每个小区间的长度为h=(b-a)/n。
分别计算每个小区间的面积,然后把所有面积加起来,得到总面积。
对于梯形法,每个小区间的面积为矩形面积加上梯形面积,矩形面积为f(x)或f(x+h),梯形面积为(h/2)*(f(x)+f(x+h)),其中f(x)为被积函数在x处的函数值。
对于辛普森法,每个小区间的面积被拆分成两个小区间,每个小区间都是一个梯形和一个三角形,分别计算每个小区间的面积,然后把所有面积加起来,得到总面积。具体计算公式为:S=(h/6)*(f(x)+4f((x+x+h)/2)+f(x+h))。
将总面积乘以区间长度(h),即可得到数值积分的近似值。
代码如下:
//定义梯形法函数 double trapezoidal_rule(double (*f)(double), double a, double b, int n) { double h = (b - a) / n; double sum = 0.0;
//计算每个小区间的面积
for(int i = 1; i < n; i++)
{
double x = a + i * h;
sum += f(x);
}
//加上两端的矩形面积和梯形面积
sum += (f(a) + f(b)) / 2.0;
sum *= h;
return sum;
}
//定义辛普森法函数 double simpson_rule(double (*f)(double), double a, double b, int n) { double h = (b - a) / n; double sum = 0.0;
//计算每个小区间的面积
for(int i = 1; i < n; i++)
{
double x1 = a + (i - 1) * h;
double x2 = a + i * h;
double x3 = a + (i + 1) * h;
sum += (f(x1) + 4 * f(x2) + f(x3));
}
//加上两端的面积
sum += (f(a) + f(b) + 4 * f((a + b) / 2.0));
sum *= h / 6.0;
return sum;
}
//测试代码
double func(double x) { return sin(x); }
int main() { double a = 0; double b = 3.1415; int n = 100;
double res1 = trapezoidal_rule(func, a, b, n);
double res2 = simpson_rule(func, a, b, n);
printf("梯形法结果:%.10f\n", res1);
printf("辛普森法结果:%.10f\n", res2);
return 0;
}