表达式求值是进行数据处理的最基本操作。请编写程序完成一个简单算术表达式的求值。要求如下:
(1) 运算符包括:+、-、* 、/、^(乘方)、括号
(2)运算量为数值常量,根据自己的能力可以对运算量做不同的约束,例如1位整数、多位整数、实数等(会有不同的测试用例);
输入:一行,即表达式,以“=”结束。例如:
5*(8-3)+6/5=
输出:一行,即表达式的值。结果值为整数时输出为整数,如果有小数时保留5位小数。
26.20000
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include<iostream>
using namespace std;
const double eps=1e-20;
stack<char> op;
stack<double> num;
double cal(double x1,double x2,char c)
{
double x;
switch (c)
{
case '+': x = x1 + x2; break;
case '-': x = x2 - x1; break;
case '*': x = x1 * x2; break;
case '/': x = x2 / x1; break;
case '^': x = pow(x2,x1); break;
}
return x;
}
void push()///将前两个数进行计算,并并将其放入栈中
{
double x1 = num.top(); num.pop();
double x2 = num.top(); num.pop();
num.push(cal(x1,x2,op.top()));
op.pop();///符号弹栈
}
int main()
{
char s[1010];
scanf("%s",s+1);
int len = strlen(s+1);
s[0] = '(';
s[len] = ')';
for (int i = 0; i <= len; i++)
{
if (s[i] == '(') op.push(s[i]);
else if (isdigit(s[i]))///提取数字
{
int pos,sign = 0;
double sum = 0;
while (isdigit(s[i])||s[i]=='.')
{
if (s[i] == '.')
{
pos = i;
sign = 1;
}
else sum=sum*10+s[i]-'0';
i++;
}
i--;
if(sign==1) num.push(sum/pow(10,i-pos));
else num.push(sum);
}
else if (s[i] == '+' || s[i] == '-')///优先级最低,可以进行前面的运算
{
while (op.top() != '(')
push();
op.push(s[i]);
}
else if (s[i] == '*' || s[i] == '/')
{
char OP=op.top();
if (OP == '*'||OP == '/'||OP == '^')///只能进行*,/,^
{
push();
if(OP == '^'&&op.top()=='/')///除法需要先计算
push();
}
op.push(s[i]);
}
else if (s[i] == '^')
{
if (op.top() == '^')///只能进行^
push();
op.push(s[i]);
}
else if (s[i] == ')')
{
while (op.top()!= '(') push();///进行括号内的运算
op.pop();
}
}
double ans=num.top();
if(ans-(long long)ans<eps)
printf("%.0lf\n", num.top());
else
printf("%.5lf\n", num.top());
return 0;
}
4/8更新
发现bug:
1)-2*5=无法运算,负数的运算没处理
2)3+(5)=无法计算,括号内只有一个数没处理
给出几个样例:
3+5^2/2-3*4+7/5^(3-1)*2=
4.06
(3+7.5)/7/5^(3-2)*7^(2*3)-1=
35293.7
(3+7.5)/7-2^4/(5-2)^(3-2)*7^(2*3)-1=
-627460.83333
8*5/3+50/(1^10-55)^2*7=
13.45336
-2*5=
-10
2+7+(10)=
19
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include<iostream>
using namespace std;
const double eps=1e-30;
stack<char> op;
stack<double> num;
double cal(double x1,double x2,char c)
{
double x;
switch (c)
{
case '+': x = x1 + x2; break;
case '-': x = x2 - x1; break;
case '*': x = x1 * x2; break;
case '/': x = x2 / x1; break;
case '^': x = pow(x2,x1); break;
}
return x;
}
void push()///将前两个数进行计算,并并将其放入栈中
{
double x1 = num.top(); num.pop();
double x2 =0;
char c='+';
if(!num.empty())/// 2)防止括号内只有一个数
{
x2= num.top();
num.pop();
c=op.top();
op.pop();///符号弹栈
}
num.push(cal(x1,x2,c));
}
int main()
{
char s[1010];
scanf("%s",s+1);
int len = strlen(s+1);
s[0] = '(';
s[len] = ')';
for (int i = 0; i <= len; i++)
{
if (s[i] == '(') op.push(s[i]);
else if (isdigit(s[i]))///提取数字
{
int pos,sign = 0;
double sum = 0;
while (isdigit(s[i])||s[i]=='.')
{
if (s[i] == '.')
{
pos = i;
sign = 1;
}
else sum=sum*10+s[i]-'0';
i++;
}
i--;
if(s[i-1]=='-'&&s[i-2]=='(')///1)处理负数,防止-2+5=的情况
{
sum*=-1;
op.pop();
}
if(sign==1) num.push(sum/pow(10,i-pos));
else num.push(sum);
}
else if (s[i] == '+' || s[i] == '-')///优先级最低,可以进行前面的运算
{
while (op.top() != '(')
push();
op.push(s[i]);
}
else if (s[i] == '*' || s[i] == '/')
{
char OP=op.top();
if (OP == '*'||OP == '/'||OP == '^')///只能进行*,/,^
{
push();
if(OP == '^'&&op.top()=='/')///除法需要先计算,再乘法:1/5^2*25
push();
}
op.push(s[i]);
}
else if (s[i] == '^')
{
if (op.top() == '^')///只能进行^
push();
op.push(s[i]);
}
else if (s[i] == ')')
{
while (op.top()!= '(') push();///进行括号内的运算
op.pop();///'('弹栈
}
}
double ans=num.top();
if(abs(ans-(long long)ans)<=eps)
printf("%.0lf\n", ans);
else
printf("%.5lf\n", ans);
return 0;
}
/*(3+7.5)/7-2^4/(5-2)^(3-2)*7^(2*3)-1=*/