HJ54 表达式求值(java)
描述
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过 100 ,合法的字符包括 ”+, -, *, /, (, )” , ”0-9” 。
输入描述:
输入算术表达式
输出描述:
计算出结果值
实现思路
我的基本思路(仅供参考):首先计算括号里面的表达式,每次分离出来括号内的内容单独计算,这样每次计算就仅仅是加减乘除的运算了;再其次,当括号内的内容计算完成后,将原有的表达式的括号部分替换成计算出来的值,直至所有括号内容全部被替换;因为不用考虑表达式是否合法的问题(括号匹配),那么将最后的表达式进行计算则可以得出结果。
需要注意:①判定括号的逻辑:是最后一个左括号和左括号后的第一个右括号,这里需要判定的是右括号的下标是否大于左括号,在代码25行处;②加减乘除运算优先级:乘除运算优先级要大于加减运算,我在此处给出的解决办法是:当遇到下一个运算符时,需要判定上一个运算符是否为’‘、’/‘运算,如果是,则需要先进行’‘、’/‘运算,将两个运算数取出做运算然后将结果放入栈,再遇到下一个运算符的时候,再判定当前的运算符是否为’‘or’/‘,这样最后最多只剩下一个’‘or’/‘运算,更好计算;③减法运算会得出负数:减法运算时,需要特殊处理,其一是因为结果可能为负数,其二是因为可能是两个负数相减,这里我的处理方法是,判定当前符号是否为’-‘,若是’-‘,那么我将’-x’一起存入栈,在最后做减法操作时,和前一个数相加,这样处理起来相较于直接运算更为便捷,不用再考虑复杂情况,但也因此,出现’-'运算符时还需考虑是否需要将该运算符入栈,判定条件为if (!cStack.size() == numStack.size() - 1 || !cStack.size() == numStack.size() - 2),若剩余的运算符和运算数差值大于2,则需要该运算符,此时入栈,否则仅仅入栈两个运算数,在最后运算时,把仅存的两个运算数相加即可,不需要该运算符;④入栈出栈逻辑:如果没有遇到运算符,则在原来的字符串(若存在)后append该字符,当且仅当上一个运算数结束了才会遇到运算符时,则此时将存有数值的字符串转换成Integer类型并存入数值栈(numStack),若运算符栈(cStack)非空,则按照第②步运算逻辑根据在栈中的运算符(上一个运算符)运算。
上述代码可简化,分离括号逻辑可以重新在另一个函数中完成,主函数仅仅完成传输表达式和得出结果并替换字符串(若需要)的操作即可。
总之,代码很丑陋,思路很大众,大家做个参考,有更好的想法欢迎评论。
附上我未删注释的代码块:
代码(JAVA)
import java.util.Scanner;
import java.util.Stack;
/*
描述
给定一个字符串描述的算术表达式,计算出结果值。
输入字符串长度不超过 100 ,合法的字符包括 ”+, -, *, /, (, )” , ”0-9” 。
输入描述:
输入算术表达式
输出描述:
计算出结果值
*/
public class Demo23ValueOfExpression {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextLine()) {
String str = in.nextLine();
StringBuffer sbf = new StringBuffer(str);
char[] cs = str.toCharArray();
int flag = 0;
while (flag >= 0) {
int start = 0;
int end = cs.length;
for (int i = 0; i < cs.length; i++) {
if (cs[i] == '(') {
start = i;
flag++;
}
}
for (int i = 0; i < cs.length; i++) {
if (cs[i] == ')' && i > start) {
end = i;
break;
}
}
// System.out.println("start = " + start + "end = " + end);
StringBuilder sbu = new StringBuilder();
// 将'('与')'中间的值提取出来计算
if (flag > 0) {
for (int i = start+1; i < end; i++) {
sbu.append(cs[i]);
}
flag -= 2;
} else if (flag == 0) {
flag -= 1;
for (int i = 0; i < cs.length; i++) {
sbu.append(cs[i]);
}
break;
}
// System.out.println("exp : " + sbu.toString());
String res = compute(sbu.toString());
//将计算结果字符串替换本来的字符串
sbf.replace(start, end+1, res);
cs = sbf.toString().toCharArray();
// System.out.println(flag);
// 继续循环
}
String result = compute(sbf.toString());
System.out.println(result);
}
in.close();
}
// 按照优先级计算算术式
// 此算术式为最简单的+、-、*、/运算式
static String compute(String exp) {
// System.out.println("exp:" + exp);
Stack<Character> cStack = new Stack<>();
Stack<Integer> numStack = new Stack<>();
StringBuilder sbu = new StringBuilder();
int result = 0;
char[] cs = exp.toCharArray();
for (char c : cs) {
if (c == '*' || c == '/' || c == '+' || c == '-') {
if (!sbu.toString().equals("")) {
int num = Integer.parseInt(sbu.toString());
numStack.push(num);
// System.out.println("pushed num = " + num);
if (!cStack.isEmpty()) {
char com = cStack.pop();
// System.out.println("got compute :" + com);
if (com == '*') {
int num2 = numStack.pop();
int num1 = numStack.pop();
// System.out.println("num1 :" + num1);
// System.out.println("num2 :" + num2);
numStack.push(num1 * num2);
// System.out.println("pushed * num = " + num1 * num2);
} else if (com == '/') {
int num2 = numStack.pop();
int num1 = numStack.pop();
// System.out.println("num1 :" + num1);
// System.out.println("num2 :" + num2);
numStack.push(num1 / num2);
// System.out.println("pushed / num = " + num1 / num2);
} else if (com == '-') {
int num2 = numStack.pop();
// System.out.println("num2 :" + num2);
numStack.push(0 - num2);
if (cStack.size() == numStack.size() - 1 || cStack.size() == numStack.size() - 2) {
} else {
cStack.push(com);
// System.out.println("pushed - num = " + (0 - num2));
}
} else {
cStack.push(com);
// System.out.println("Repushed compute : " + com);
}
}
sbu = new StringBuilder();
}
cStack.push(c);
// System.out.println("pushed compute : " + c);
} else {
sbu.append(c);
}
}
int num = Integer.parseInt(sbu.toString());
numStack.push(num);
// System.out.println("pushed num == " + num);
if (!cStack.isEmpty()) {
char com = cStack.pop();
// System.out.println("got compute :" + com);
if (com == '*') {
int num2 = numStack.pop();
int num1 = numStack.pop();
numStack.push(num1 * num2);
// System.out.println("pushed * num = " + num1 * num2);
} else if (com == '/') {
int num2 = numStack.pop();
int num1 = numStack.pop();
numStack.push(num1 / num2);
// System.out.println("pushed / num = " + num1 / num2);
} else if (com == '-') {
int num2 = numStack.pop();
numStack.push(0 - num2);
// System.out.println("pushed - num = " + (0 - num2));
// System.out.println(cStack.size());
// System.out.println(numStack.size());
if (cStack.size() == numStack.size() - 1 || cStack.size() == numStack.size() - 2) {
} else {
cStack.push(com);
// System.out.println("Repushed comoute = " + com);
}
} else {
cStack.push(com);
// System.out.println("Repushed compute : " + com);
}
}
while ((!cStack.isEmpty()) || (numStack.size() >= 2)) {
if (numStack.size() == 1) {
break;
}
int num2 = numStack.pop();
// System.out.println("num2 :" + num2);
int num1 = numStack.pop();
// System.out.println("num1 :" + num1);
char c = '+';
if (cStack.isEmpty()) {
} else {
c = cStack.pop();
// System.out.println("compute:" + c);
}
if (c == '+') {
numStack.push(num1 + num2);
// System.out.println("+" + (num1 + num2));
} else if (c == '-') {
numStack.push(num1 + num2);
// System.out.println("-" + (num1 + num2));
} else if (c == '*') {
numStack.push(num1 * num2);
// System.out.println("*" + (num1 * num2));
// System.out.println("size = " + numStack.size());
} else if (c == '/') {
numStack.push(num1 / num2);
// System.out.println("/" + (num1 / num2));
}
}
result = numStack.pop();
// System.out.println("result:" + result);
return String.valueOf(result);
}
}
测试
测试数据
// 3*5+8-0*3-6+0+0
// 5-3+9*6*(6-10-2)
// 4+(6*(4*7-9*(0-8-4)*2))
// (7+4*3+10*(3-3+4-1-8-10))
// 2+(4*5+1)*8+7*4+10-9+3+1*9-(6-0*4*4)
// 9+3-5-10-2*10*(10+3+(4*1-10+5)-(9*5*1+5-7))
测试结果
3*5+8-0*3-6+0+0
17
5-3+9*6*(6-10-2)
-322
4+(6*(4*7-9*(0-8-4)*2))
1468
(7+4*3+10*(3-3+4-1-8-10))
-131
2+(4*5+1)*8+7*4+10-9+3+1*9-(6-0*4*4)
205
9+3-5-10-2*10*(10+3+(4*1-10+5)-(9*5*1+5-7))
617