表达式计算器
Posted maoruimas
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了表达式计算器相关的知识,希望对你有一定的参考价值。
#include<bits/stdc++.h>
using namespace std;
enum Atom_type{NUMBER=1,LETTER=2,OPERATOR=3};
const int MAX_PARA=20;
int sign[128],prio[128],n_para;
vector<double> para_list_all[MAX_PARA];
//double para_list[MAX_PARA];
vector<string> parameters;
int gcd(int n,int m){
if(n<0)n=-n;
if(m<0)m=-m;
while(m){
n=n%m;
swap(n,m);
}
return n;
}
struct Mocular{
pair<int,int> coef;
int cnt_pow[MAX_PARA];
Mocular(){
coef.first=coef.second=0;
memset(cnt_pow,0,sizeof cnt_pow);
}
Mocular(const Mocular &a){
coef=a.coef;
for(int i=0;i<n_para;++i)cnt_pow[i]=a.cnt_pow[i];
}
Mocular(int n){
coef={1,1};
memset(cnt_pow,0,sizeof cnt_pow);
if(n%10==NUMBER)coef={n/10,1};
else cnt_pow[n/10]++;
}
void reduce(){
int n_gcd=gcd(coef.first,coef.second);
if(n_gcd){
coef.first/=n_gcd;
coef.second/=n_gcd;
}
if(coef.second<0){
coef.first*=(-1);
coef.second*=(-1);
}
}
Mocular operator * (const Mocular &a){
Mocular ret(*this);
ret.coef.first*=a.coef.first;
ret.coef.second*=a.coef.second;
for(int i=0;i<n_para;++i)ret.cnt_pow[i]+=a.cnt_pow[i];
ret.reduce();
return ret;
}
Mocular operator / (const Mocular &a){
Mocular ret(*this);
ret.coef.first*=a.coef.second;
ret.coef.second*=a.coef.first;
for(int i=0;i<n_para;++i)ret.cnt_pow[i]-=a.cnt_pow[i];
ret.reduce();
return ret;
}
bool operator == (const Mocular &a){
bool flag=true;
for(int i=0;i<n_para;++i)
if(cnt_pow[i]!=a.cnt_pow[i])flag=false;
return flag;
}
void print(){
int a=coef.first,b=coef.second;
if(a==0)return;
if(a>0)cout<<'+';
else{
cout<<'-';
a=-a;
}
cout<<" ";
if(a!=1&&b==1)cout<<a<<" ";
else if(b!=1)cout<<a<<"/"<<b<<" ";
bool flag=true;
for(int i=0;i<n_para;++i)
if(cnt_pow[i]){
cout<<parameters[i];
if(cnt_pow[i]!=1)cout<<'^'<<cnt_pow[i];
cout<<" ";
flag=false;
}
if(flag&&a==1&&b==1)cout<<"1 ";
}
};
struct Expression{
vector<Mocular> exp;
Expression(){exp.clear();}
Expression(const Expression &a){
exp.clear();
for(auto &x: a.exp)exp.emplace_back(x);
}
Expression(const Mocular &a){
exp.clear();
exp.emplace_back(a);
}
Expression operator + (const Expression &a){
Expression ret(*this);
for(auto &x: a.exp){
bool flag=true;
for(auto &y: ret.exp)
if(y==x){
y.coef.first=y.coef.first*x.coef.second+y.coef.second*x.coef.first;
y.coef.second*=x.coef.second;
y.reduce();
flag=false;
break;
}
if(flag)ret.exp.push_back(x);
}
return ret;
}
Expression operator - (const Expression &a){
Expression ret(a);
for(auto &x: ret.exp)x.coef.first*=(-1);
return *this+ret;
}
Expression operator * (const Expression &a){
Expression ret;
for(auto &x: exp)
for(auto &y: a.exp)
ret=ret+Expression(x*y);
return ret;
}
Expression operator / (const Expression &a){
Expression ret;
for(auto &x: exp)
ret=ret+Expression(x/a.exp[0]);
return ret;
}
Expression power(int n){
Expression ret(Mocular(11)),a(*this);
if(n==0)return ret;
while(n){
if(n&1)ret=ret*a;
a=a*a;
n>>=1;
}
return ret;
}
void print(){
for(auto &x: exp)x.print();
cout<<endl;
}
};
void init(){
for(int i=1;i<128;++i)sign[i]=LETTER;
for(int i='0';i<='9';++i)sign[i]=NUMBER;
sign['.']=NUMBER;
sign[0]=sign['+']=sign['-']=sign['*']=sign['/']=sign['^']=sign['(']=sign[')']=OPERATOR;
prio['+']=prio['-']=1;
prio['*']=prio['/']=2;
prio['^']=3;
}
bool format(string &s,vector<int> &v){
string tps,rts;
v.clear();
//formating s to a standard expression as well as detecting all errors
if(sign[s[0]]==OPERATOR){
switch(s[0]){
case '+':s.erase(s.begin());break;
case '-':s.insert(s.begin(),'0');break;
case '*':case '/':case '^':case ')':return false;
default:break;
}
}
for(int i=0,n_b=0;i<s.size();){
switch(sign[s[i]]){
case NUMBER:
if(rts.size()&&rts.back()==')')return false;
for(;sign[s[i]]==NUMBER;++i)rts+=s[i];
break;
case LETTER:
if(rts.size()&&rts.back()==')')return false;
if(rts.size()&&sign[rts.back()]==NUMBER)rts+='*';
tps.clear();
if(s[i]=='['){
for(;i<s.size();++i){
rts+=s[i],tps+=s[i];
if(s[i]==']')break;
}
if(i==(int)s.size())return false;
else i++;
}else for(;sign[s[i]]!=OPERATOR;++i)rts+=s[i],tps+=s[i];
parameters.emplace_back(tps);
break;
case OPERATOR:
if(s[i]=='(')n_b++;
else if(s[i]==')')n_b--;
if(n_b<0)return false;
if(sign[rts.back()]==OPERATOR){
switch(s[i]){
case '+':case '-':
if(rts.back()!='('&&rts.back()!=')')return false;
if(rts.back()=='(')rts+='0';
break;
case '*':case '/':case '^':if(rts.back()!=')')return false;break;
case '(':if(rts.back()==')')rts+='*';break;
case ')':
if(rts.back()=='(')rts.pop_back();
else if(rts.back()!=')')return false;
break;
}
}else if(s[i]=='(')rts+='*';
rts+=s[i++];
break;
}
}
if(sign[rts.back()]==OPERATOR&&rts.back()!=')')return false;
s=rts;
//prepare parameters
sort(parameters.begin(),parameters.end());
n_para=unique(parameters.begin(),parameters.end())-parameters.begin();
parameters.resize(n_para);
//to code
for(int i=0,n;i<s.size();){
switch(sign[s[i]]){
case NUMBER:
for(n=0;sign[s[i]]==NUMBER;++i)
n=n*10+s[i]-'0';
v.push_back(n*10+NUMBER);
break;
case LETTER:
tps.clear();
if(s[i]=='['){
for(;i<s.size();++i){
tps+=s[i];
if(s[i]==']')break;
}
i++;
}else for(;sign[s[i]]!=OPERATOR;++i)tps+=s[i];
n=lower_bound(parameters.begin(),parameters.end(),tps)-parameters.begin();
v.push_back(n*10+LETTER);
break;
case OPERATOR:
n=s[i++];
v.push_back(n*10+OPERATOR);
break;
}
}
return true;
}
void RPN(vector<int> &v){
vector<int> v1,v2;
for(auto &x: v){
switch(x%10){
case NUMBER:
case LETTER:
v2.push_back(x);
break;
case OPERATOR:
if(char(x/10)=='(')v1.push_back(x);
else if(char(x/10)==')'){
while(char(v1.back()/10)!='('){
v2.push_back(v1.back());
v1.pop_back();
}
v1.pop_back();
}else if(v1.empty())v1.push_back(x);
else if(prio[v1.back()/10]<prio[x/10])v1.push_back(x);
else{
while(!v1.empty()&&prio[v1.back()/10]>=prio[x/10]){
v2.push_back(v1.back());
v1.pop_back();
}
v1.push_back(x);
}
break;
}
}
while(!v1.empty()){
v2.push_back(v1.back());
v1.pop_back();
}
v=v2;
}
void simplificate(vector<int> &v){
vector<Expression> v1;
Expression t1,t2;
for(auto &x: v){
switch(x%10){
case NUMBER:
case LETTER:
v1.emplace_back(Mocular(x));
break;
case OPERATOR:
t2=v1.back();v1.pop_back();
t1=v1.back();v1.pop_back();
switch(char(x/10)){
case '+':v1.push_back(t1+t2);break;
case '-':v1.push_back(t1-t2);break;
case '*':v1.push_back(t1*t2);break;
case '/':v1.push_back(t1/t2);break;
case '^':v1.push_back(t1.power(t2.exp[0].coef.first));break;
}
break;
}
}
v1[0].print();
}
void calculate(vector<int> &v,vector<double> ¶_list){
vector<double> v1;
double t1,t2;
for(auto &x: v){
switch(x%10){
case NUMBER:
v1.emplace_back(double(x/10));
break;
case LETTER:
v1.emplace_back(para_list[x/10]);
break;
case OPERATOR:
t2=v1.back();v1.pop_back();
t1=v1.back();v1.pop_back();
switch(char(x/10)){
case '+':v1.push_back(t1+t2);break;
case '-':v1.push_back(t1-t2);break;
case '*':v1.push_back(t1*t2);break;
case '/':v1.push_back(t1/t2);break;
case '^':v1.push_back(pow(t1,t2));break;
}
break;
}
}
cout<<v1[0]<<endl;
}
char get_num_char(string &s){//for get_num()
char _head=s[0];
if((_head>='0'&&_head<='9')||_head=='-'||_head=='+'||_head=='.'||_head=='e'||_head=='E'){
s.erase(s.begin());
return _head;
}else return 0;
}
double get_num_double(string &s){
int figure=0,power=0,fixed=0,sig_figure=1,sig_power=1;
bool power_mode=false,exist_error=false;
char ch;
double ret;
while(ch=get_num_char(s)){
if(ch=='-'&&!power_mode)sig_figure=-1;
else if(ch=='-'&&power_mode)sig_power=-1;
else if(ch=='+'&&!power_mode)sig_power=1;
else if(ch=='+'&&power_mode)sig_power=1;
else if(ch>='0'&&ch<='9'&&!power_mode)figure=figure*10+ch-'0';
else if(ch>='0'&&ch<='9'&&power_mode)power=power*10+ch-'0';
else if(ch=='.'&&!power_mode&&fixed==0){
while(s[fixed]>='0'&&s[fixed]<='9')fixed++;
}else if(tolower(ch)=='e'&&!power_mode&&power==0)power_mode=true;
else{
exist_error=true;
break;
}
}
//return {sig_figure*figure,sig_power*power-fixed};
ret=sig_figure*figure;
fixed=sig_power*power-fixed;
while(fixed>0){
ret*=10;
fixed--;
}
while(fixed<0){
ret/=10;
fixed++;
}
return ret;
}
vector<double> tmp_para_list;
void dfs_calculate(vector<int> &v,int n=0){
if(n==n_para){
cout<<"F(";
for(int i=0;i<n_para;++i){
cout<<parameters[i]<<"="<<tmp_para_list[i];
if(i!=n_para-1)cout<<",";
else cout<<") = ";
}
calculate(v,tmp_para_list);
return;
}
for(auto x: para_list_all[n]){
tmp_para_list.push_back(x);
dfs_calculate(v,n+1);
tmp_para_list.pop_back();
}
}
int main(){
ios::sync_with_stdio(0);
string s;
double _from,_to,_step;
vector<int> v;
init();
cout<<"FBI Warning : power should be positive integer, denominator should be as simple as possible, or simplification may not be correct
";
while(cin>>s){
parameters.clear();
n_para=0;
if(format(s,v)){
cout<<"| Your input: "<<s<<endl<<"| Parameters:
";
for(int i=0;i<n_para;++i)cout<<"| "<<i<<" - "<<parameters[i]<<endl;
//cout<<"| Tansformed code: ";
//for(auto &x: v)cout<<x<<" ";cout<<endl;
RPN(v);
//cout<<"| RPN Code: ";
//for(auto &x: v)cout<<x<<" ";cout<<endl;
simplificate(v);
cout<<"| ";
for(auto &x: parameters)cout<<x<<" ";cout<<endl;
for(int i=0;i<n_para;++i){
para_list_all[i].clear();
cin>>s;
if(s[0]>='0'&&s[0]<='9')para_list_all[i].push_back(get_num_double(s));
else if(s[0]=='{'){
s.erase(s.begin());
while(_from=get_num_double(s)){
para_list_all[i].push_back(_from);
if(s[0]=='}')break;
else s.erase(s.begin());
}
}else if(s[0]=='['){
s.erase(s.begin());
_from=get_num_double(s);
s.erase(s.begin());
_to=get_num_double(s);
s.erase(s.begin());
_step=get_num_double(s);
for(;_from<_to+1e-7;_from+=_step)para_list_all[i].push_back(_from);
}
}
//for(auto x: para_list_all[0])cout<<x<<" ";cout<<endl;
tmp_para_list.clear();
dfs_calculate(v);
}
else cout<<"error
";
cout<<endl;
}
return 0;
}
以上是关于表达式计算器的主要内容,如果未能解决你的问题,请参考以下文章