表達式求值是進行數據處理的最基本操作。請編寫程序完成一個簡單算術表達式的求值。要求如下:
(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=*/