一般我们见到的算术表达式都是中缀表达式。
如:1 + 2 * (4 - 2) - 3
此时我们的运算思路就是先计算括号中的数,然后计算乘数,最后计算加减。算数运算规则:
1:运算符优先级高的先运算。
2:先括号内,后括号外。
3:同级别先左后右。
但是显然对于计算机来说不太方便计算和判断。因此为把它转换为后缀表达式来计算。
后缀表达式:1242-*+3-
运算符的优先级:
| 操作符 | 优先级 |
|---|---|
| + - | 1 |
| * / | 2 |
| ^ | 3 |
| ! l o g s c t | 4 |
| 操作符 | 含义 |
|---|---|
| ! | 阶乘的运算 |
| l | 对数ln的运算 |
| o | 对数log2的运算 |
| g | 开根号的运算 |
| s | 三角函数sin的运算 |
| c | 三角函数cos的运算 |
| t | 三角函数tan的运算 |
思路:
1.遇到数字就加入到后缀表达式链表中。
2.遇到左括号’('就直接入栈。
3.遇到操作符优先级比栈顶操作符优先级低的话,就把栈中优先级大于等于它的依次输出,直到遇到
(1.优先级比它小的
(2.或者是左括号时
(3.或者栈为空时
这三种情况停止出栈,出栈的操作符全部依次加入到后缀表达式链表中。并且把此时的操作符入栈。
4.遇到右括号时,操作符一直出栈,出栈的操作符全部依次加入到后缀表达式链表中。直到遇到左括号是停止,且右括号不入栈。
6.当循环完毕时把栈中的操作符全部出栈,加入后缀表达式链表中。
过程:
| 步骤 | 中缀表达式 | 堆栈 | 后缀表达式 |
|---|---|---|---|
| 1 | 1+2*(4-2)-3 | ||
| 2 | +2*(4-2)-3 | 1 | |
| 3 | 2*(4-2)-3 | + | 1 |
| 4 | *(4-2)-3 | + | 12 |
| 5 | (4-2)-3 | +* | 12 |
| 6 | 4-2)-3 | +*( | 12 |
| 7 | -2)-3 | +*( | 124 |
| 8 | 2)-3 | +*(- | 124 |
| 9 | )-3 | +*(- | 1242 |
| 10 | )-3 | +*( | 1242- |
| 11 | )-3 | +* | 1242- |
| 12 | -3 | +* | 1242- |
| 13 | -3 | + | 1242-* |
| 15 | -3 | 1242-*+ | |
| 16 | 3 | - | 1242-*+ |
| 17 | - | 1242-*+3 | |
| 18 | 1242-*+3- |
此时的运算过程为:
遇到数字入栈,遇到操作符出栈运算,并把计算得到的值入栈。
| 步骤 | 后缀表达式 | 栈堆 | 运算 |
|---|---|---|---|
| 1 | 1242-*+3- | ||
| 2 | 242-*+3- | 1 | |
| 3 | 42-*+3- | 12 | |
| 4 | 2-*+3- | 124 | |
| 5 | -*+3- | 1242 | |
| 6 | *+3- | 12 | 4-2=2 |
| 7 | *+3- | 122 | |
| 8 | +3- | 1 | 2*2=4 |
| 9 | +3- | 14 | |
| 10 | 3- | 1+4=5 | |
| 11 | 3- | 5 | |
| 12 | - | 53 | |
| 13 | 5-3=2 | ||
| 14 | 2 |
所以最后得到的值为2。我上面定义的其它操作符也可以用。这里就不举例子了。
我用这个方法写过一个带界面的科学计算器。有兴趣的话可以看看。链接如下:
java实现科学计算器
方法实现的代码如下:
private ListzhongZhui(String str) {//把输入的字符串转换成中缀表达式。存入list中 int index = 0; List list = new ArrayList<>(); do{ char ch = str.charAt(index); if("+-*/^!logsct()".indexOf(str.charAt(index)) >= 0){ //是操作符,直接添加至list中 index ++; list.add(ch+""); }else if (str.charAt(index) == 'e' || str.charAt(index) == 'p'){ index ++; list.add(ch+""); } else if("0123456789".indexOf(str.charAt(index)) >= 0){ //是数字,判断多位数的情况 String str1 = ""; while (index < str.length() && "0123456789.".indexOf(str.charAt(index)) >= 0){ str1 += str.charAt(index); index ++; } list.add(str1); } }while (index < str.length()); return list; } public List houZhui(List list){//中缀表达式转换称后缀表达式 Stack fuZhan = new Stack<>(); List list2 = new ArrayList<>(); if (!list.isEmpty()) { for (int i = 0; i < list.size(); i++) { if (isNumber(list.get(i))){ list2.add(list.get(i)); } else if (list.get(i).charAt(0) == '('){ fuZhan.push(list.get(i)); } else if (isOperator(list.get(i)) && list.get(i).charAt(0) != '('){ if (fuZhan.isEmpty()){ fuZhan.push(list.get(i)); } else {//符栈不为空 if (list.get(i).charAt(0) != ')'){ if (adv(fuZhan.peek()) <= adv(list.get(i))){ //入栈 fuZhan.push(list.get(i)); } else {//出栈 while (!fuZhan.isEmpty() && !"(".equals(fuZhan.peek())){ if(adv(list.get(i)) <= adv(fuZhan.peek())){ list2.add(fuZhan.pop()); } } if (fuZhan.isEmpty() || fuZhan.peek().charAt(0) == '('){ fuZhan.push(list.get(i)); } } } else if (list.get(i).charAt(0) == ')'){ while (fuZhan.peek().charAt(0) != '('){ list2.add(fuZhan.pop()); } fuZhan.pop(); } } } } while (!fuZhan.isEmpty()){ list2.add(fuZhan.pop()); } } // else { // jTextField1.setText(""); // } return list2; } public static boolean isOperator(String op){//判断是否为操作符 if ("0123456789.ep".indexOf(op.charAt(0)) == -1) { return true; } else { return false; } } public static boolean isNumber(String num){//判断是否为操作数 if ("0123456789ep".indexOf(num.charAt(0)) >= 0) { return true; } else { return false; } } public static int adv(String f){//判断操作符的优先级 int result = 0; switch(f) { case "+": result = 1; break; case "-": result = 1; break; case "*": result = 2; break; case "/": result = 2; break; case "^": result = 3; break; case "!": result = 4; break; case "g": result = 4; break; case "l": result = 4; break; case "o": result = 4; break; case "s": result = 4; break; case "c": result = 4; break; case "t": result = 4; break; } return result; } public double math(List list2) {//通过后缀表达式进行计算 Stack stack = new Stack (); for (int i = 0; i < list2.size(); i++) { if (isNumber(list2.get(i))) { stack.push(list2.get(i)); } else if (isOperator(list2.get(i))){ double res = 0; if (list2.get(i).equals("+")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 + num2; } else if (list2.get(i).equals("-")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 - num2; } else if (list2.get(i).equals("*")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = num1 * num2; } else if (list2.get(i).equals("/")) {//除数不能为0 double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); if (num2 != 0){ res = num1 / num2; } else { System.out.println("除数不能为0"); //indexYN = 1; } } else if (list2.get(i).equals("^")) { double num2 = Double.parseDouble(stack.pop()); double num1 = Double.parseDouble(stack.pop()); res = Math.pow(num1, num2); } else if (list2.get(i).equals("!")) {//阶乘必须为自然数 double num1 = Double.parseDouble(stack.pop()); if (num1 == 0 || num1 == 1){ res = 1; } else if (num1 == (int)num1 && num1 > 1){ int d = 1; for (int j = (int)num1; j >0; j--) { d *= j; } res = d; } else { System.out.println("阶乘必须为自然数"); //indexYN = 1; } } else if (list2.get(i).equals("g")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sqrt(num1); } else if (list2.get(i).equals("l")) {//ln的x必须大于0 double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1); } else { System.out.println("ln的x必须大于0"); // indexYN = 1; } } else if (list2.get(i).equals("o")) {//log的x必须大于0 double num1 = Double.parseDouble(stack.pop()); if (num1 > 0){ res = Math.log(num1) / Math.log(2); } else { System.out.println("log的x必须大于0"); //indexYN = 1; } } else if (list2.get(i).equals("s")) { double num1 = Double.parseDouble(stack.pop()); res = Math.sin(num1); } else if (list2.get(i).equals("c")) { double num1 = Double.parseDouble(stack.pop()); res = Math.cos(num1); } else if (list2.get(i).equals("t")) {//tan的x不能为+-(π/2 + kπ) double num1 = Double.parseDouble(stack.pop()); if (Math.cos(num1) != 0){ res = Math.tan(num1); } else { System.out.println("tan的x不能为+-(π/2 + kπ)"); // indexYN = 1; } } stack.push("" + res); } } if (indexYN == 0){ if (!stack.isEmpty()){ return Double.parseDouble(stack.pop()); } else { return 0; } } else { return -999999; } }



