您的位置:首页 > 其它

赛码网基础算法——简单计算(求解加减乘除等复杂算式)

2017-04-11 19:54 447 查看
题目转自赛码网

1、题目:

  小赛所在的小组主要负责WEB应用的开发工作,这次他所在的小组正在开发一个WEB版的财务软件。

  为方便用户使用,他们打算为用户提供一个简单计算功能,用户输入数学算式,就可以得到计算结果。

  其中涉及的计算包括:”+”、”-”、”*”、”/”、”^”、”(”、”)”,分别表示加减乘除和指数,其中括号用于调整计算的顺序。合法的表达式如下:

  x+y+z

  x+(y+z)

  x*(y+z)+a-b-c^d

  小赛对此不太精通,因此请你帮忙编写这个程序。

  输入

  输入数据有多行,每行为一个用户输入的算式,保证算式是合法的,每行最多包含不超过200个字符。所有参与运算的数值均为整数,若为指数,则为正整数。

  输出

  对每个算式,在单独的一行中输出计算结果,结果请输出整数。

样例输入

  1+2+3+4+5+6+7+8+9+10

  1+2*3+4

  1+2^(3+3)+5

样例输出

  55

  11

  70

2、解析:

  这个题目是一个基本算法题,但是挺费时间,需要考虑很多细节,如果出在某个IT公司笔试题中,我估计我会答不完。

  回到正题,从整个题结构来看,因为我们学习了运算法则,运算符的优先级我们很熟悉,所以能够按顺序很快计算出来。但是计算机是死的,所以需要解决的一个难题就是怎么设计规则,让计算机“知道”运算优先级。其实这块有个规则,先后两个运算符,如果后者比前者运算符优先级低的话,前者就可以正常进行计算,计算完事再进行下一次比较。反之则暂且不考虑计算,继续往公式序列后面遍历。

  说到这里,也很显然可以看出,该题适合的数据结构是栈(stack),一旦没有出现前后两个运算符满足后者比前者优先级低的条件,我就将遍历到的序列压入栈中,等到下一步取数。说的不太清楚,详细还是看下面的程序吧。

3、程序:

#include<iostream>
#include<cctype>
#include<stack>
#include<cmath>
using namespace std;
//建立前后两运算符关系:分别是'\0' , + , - , * , / , ^ , ( , )
//-1表示横对应符号比纵对应运算符优先级小,0表示平等,1表示大
const int cmp_punct[8][8] = {
{0,1,1,1,1,1,1,1},
{-1,-1,-1,1,1,1,1,-1},
{-1,-1,-1,1,1,1,1,-1},
{-1,-1,-1,-1,-1,1,1,-1},
{-1,-1,-1,-1,-1,1,1,-1},
{-1,-1,-1,-1,-1,-1,1,-1},
{0,1,1,1,1,1,1,0},
{0,-1,-1,-1,-1,-1,-1,-1}
};
//对两个数求对应的
int computeResult(int a, char op, int b){
switch(op)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
return a / b;
case '^':
return pow((double)a,(double)b);
}
}
//获取运算符对应到cmp_punct数组中索引
int getRule(char op)
{
switch(op)
{
case '\0':
return 0;
case '+':
return 1;
case '-':
return 2;
case '*':
return 3;
case '/':
return 4;
case '^':
return 5;
case '(':
return 6;
case ')':
return 7;
default:
return -1;
}
}

int main( )
{
char cArr[300]={'\0'};
while(cin.getline(cArr,200)){
int i = 0;
stack<int> digit;
stack<char> punct;
punct.push('\0');//起始端
while(!punct.empty()){
if(isdigit(cArr[i])){ //如果一直是数字,就加载当前数到digit数字栈中
int sum = 0;
while(isdigit(cArr[i])){
sum = sum*10 + cArr[i]-'0';
i++;
}
digit.push(sum);
}
else{          //如果是符号,就和上一个运算符比较优先级,确定上一个运算符是否展开运算
int first = getRule(punct.top());
int second = getRule(cArr[i]);
if(cmp_punct[first][second]  == 1){
punct.push(cArr[i++]);
}
else if(cmp_punct[first][second]  == -1){ //新运算符没有上一个运算符优先级高,上一个运算符可以运算了
int a = digit.top();
digit.pop();
int b = digit.top();
digit.pop();
digit.push(computeResult(b, punct.top(), a));
punct.pop();     //删除入栈的运算符
}
else{    //等于0则直接删除
punct.pop();
i++;
}
}
}
cout<<digit.top()<<endl;
}
return 0;
}


个人学习记录,由于能力和时间有限,如果有错误望读者纠正,谢谢!

转载请注明出处:CSDN 无鞋童鞋。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: