//c++ 作業:用兩重菜單顯示 積分函數和積分方法
#include<iostream>
#include<cmath>
using namespace std;
class Function{
public:
virtual double operator()(double x) const=0;
};
class Function1:public Function{
public:
double operator()(double x) const;
};
double Function1::operator()(double x) const{
return log(1.0+x)/(1.0+x*x);
}
class Function2:public Function{
public:
double operator()(double x) const;
};
double Function2::operator()(double x) const{
return x*x;
}
class Function3:public Function{
public:
double operator()(double x) const;
};
double Function3::operator()(double x) const{
return sin(x);
}
class Function4:public Function{
public:
double operator()(double x) const;
};
double Function4::operator()(double x) const{
return cos(x);
}
class Integration
{
public:
virtual double operator()(double a,double b,double eps)=0;
virtual ~Integration(){}
};
class Trapz1:public Integration
{
private:
Function &f;
public:
Trapz1(Function &fun):f(fun){}
double operator()(double a,double b,double eps)
{
int n=200;
double h=(b-a)/n;
double sum=0,tmp;
for(int i=1;i<n;i++)
{
tmp=2*f(a+i*h);
sum+=tmp;
}
sum=(sum+f(a)+f(b))*h/2;
return sum;
}
};//梯形法求積分
class Trapz2:public Integration
{
private:
Function &f;
public:
Trapz2(Function &fun):f(fun){}
double operator()(double a,double b,double eps)
{
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 k=0;k<n;k++)
{
double x=a+(k+0.5)*h;
sum+=f(x);
}
t2n=(tn+h*sum)/2.0;
if(fabs(tn-t2n)<eps)
done=true;
else
{
n=n*2;
h=h/2;
tn=t2n;
}
}while(!done);
return t2n;
}
};//變步長求積分
class Simpson:public Integration
{
private:
Function &f;
public:
Simpson(Function &fun):f(fun){}
virtual double operator()(double a,double b,double eps)
{
int n=400;
double h=(b-a)/(2*n);
double sum=0;
for(int i=1;i<=(2*n-1);i=i+2)
{
double tmp=4*f(a+i*h);
sum=sum+tmp;
}
for(int i=2;i<=(2*n-2);i=i+2)
{
double tmp=2*f(a+i*h);
sum=sum+tmp;
}
sum=(sum+f(a)+f(b))*h/3;
return sum;
}
};//辛普生法求積分
class Rectangle:public Integration
{
private:
Function &f;
public:
Rectangle(Function &fun):f(fun){}
virtual double operator()(double a,double b,double eps)
{
double sum=0;
int n=400;
double h=(b-a)/n;
for(int i=1;i<n;i++)
{
double tmp=h*f(a+i*h+h/2);
sum=sum+tmp;
}
return sum;
}
};//矩形法求積分
void mune1();
void mune2();
Function *fp;
Integration *tp;
int main(){
mune1();
return 0;
}
void mune1(){
int choice;
cout<<"****************************"<<endl;
cout<<"* 1.y=log(1.0+x)/(1.0+x*x)*"<<endl;
cout<<"* 2.y=x^2 *"<<endl;
cout<<"* 3.y=sin(x) *"<<endl;
cout<<"* 4.y=cos(x) *"<<endl;
cout<<"* 0.退出系統 *"<<endl;
cout<<"****************************"<<endl;
cout<<"****請選折要積分的函數******"<<endl;
cin>>choice;
switch(choice){
case 1:
fp=new Function1;
mune2();
break;
case 2:
fp=new Function2;
mune2();
break;
case 3:
fp=new Function3;
mune2();
break;
case 4:
fp=new Function3;
mune2();
break;
case 0:
break;
default:
cout<<"輸入錯誤請重新輸入!"<<endl;
}
}
void mune2(){
int flag=1,choice;
double x,y,exp;
cout<<"請輸入積分區間(x,y)和精度"<<endl;
cin>>x>>y>>exp;
while(flag){
cout<<"**********************"<<endl;
cout<<"* 1.變步長求積分 *"<<endl;
cout<<"* 2.梯形法求積分 *"<<endl;
cout<<"* 3.辛普生法求積分 *"<<endl;
cout<<"* 4.矩形法求積分 *"<<endl;
cout<<"* 5.重新輸入積分區間*"<<endl;
cout<<"* 0.返回上級菜單 *"<<endl;
cout<<"**********************"<<endl;
cout<<"****請選折求積分方法**"<<endl;
cin>>choice;
switch(choice){
case 1:
tp=new Trapz2(*fp);
flag=1;
break;
case 2:
tp=new Trapz1(*fp);
flag=1;
break;
case 3:
tp=new Simpson(*fp);
flag=1;
break;
case 4:
tp=new Rectangle(*fp);
flag=1;
break;
case 5:
cout<<"請輸入積分區間(x,y)和精度"<<endl;
cin>>x>>y>>exp;
flag=2;
break;
case 0:
flag=0;
break;
default:
cout<<"輸入錯誤請重新輸入"<<endl;
flag=2;
}
if(flag==1){
cout<<"積分結果:"<<(*tp)(x,y,exp)<<endl;
}
}
mune1();
}