使用Java求數學表示式的值
阿新 • • 發佈:2019-01-31
關於怎麼求數學表示式的值,網上有很多教程。但大多教程只是一個Demo,該Demo只實現了個位數的四則運算,遇到個位數以上的計算時就會出現問題。本文在此基礎上進行了擴充套件,實現了個位數以上的四則運算。
整體思路:
輸入的表示式為中綴表示式,將該表示式轉為後序表示式然後利用棧做運算。
中綴表示式轉字尾表示式的方法:(用list存放字尾表示式中各元素,用棧stack臨時存放運算子)
1:遇到數字時:將其放入list。
2:遇到運算子時:當運算子時乘號或者除號時直接入棧。當運算子時加減號時:若棧為空則直接入棧;否則,獲取棧頂運算子topOper(是獲取,而不是彈出,故用peek而不是pop),若topOper為左括號時,直接入棧,否則迴圈獲取棧中左括號上面的元素加入list,最後將當前運算子入棧。
3:遇到左括號(“(”)時,直接入棧;
4:遇到右括號時(“)”),依次出棧,當出棧運算子為左括號時,退出。
5:最終將棧中的各元素依次出棧放入list。
使用字尾表示式求值的方法:
依次遍歷list中的各元素進行入棧,當得到的元素為運算子時,取出棧頂的兩個元素做運算,然後將運算結果入棧,直到list遍歷完成。
程式碼如下:
import java.util.*; public class MyStackCalculators { public static void main(String[] args) { String string = "(7+4*3+10*(3-3+4-1-8-10))"; List<String> inputList = strToList(string); List<String> postfix = getPostfixExpression(inputList); String res = getRes(postfix); System.out.println("最終結果為:" + res); } /** * 獲取輸入表示式中的各元素,並用list進行儲存。 * @param expression * @return */ private static List<String> strToList(String expression) { List<String> arrayList = new ArrayList<String>(); char ch[] = expression.toCharArray(); String v = ""; for(int i=0; i<ch.length; i++) { char e = ch[i]; if(e >= '0' && e <= '9') { v += e; } else { if(v != "") { arrayList.add(v); } arrayList.add(e + ""); v = ""; } } if(v != "") { arrayList.add(v); } return arrayList; } private static List<String> getPostfixExpression(List<String> list) { List<String> pfixExpList = new ArrayList<>();//存放字尾表示式中各元素的list Stack<String> stack = new Stack<>();//存放運算子的棧 for(int i=0; i<list.size(); i++) { String tm = list.get(i); if(tm.matches("[0-9]*")) {//當得到的元素是數字時,直接放入list。 pfixExpList.add(tm); } else if(tm.equals("(")) {//當得到元素是左括號時,直接入棧 stack.push(tm); } else if(tm.equals(")")){//當得到元素是右括號時 //執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出。 String s = stack.pop(); while(!(s.equals("(")) && !stack.isEmpty()) { pfixExpList.add(s); s = stack.pop();//此語句最終會彈出左括號 } } else { //是運算子 if(tm.equals("*") || tm.equals("/")) { //乘號和除號情況,直接入棧 stack.push(tm); } else {//加減號情況,取出棧中的“(”上面的全部元素存入list1,最後將當前運算子入棧 if(stack.isEmpty()) { stack.push(tm); } else { String s = stack.peek(); if(s.equals("(")) { stack.push(tm); } else { while(!s.equals("(") && !stack.isEmpty()) { pfixExpList.add(stack.pop()); s = stack.peek(); } stack.push(tm);//將當前運算子入棧 } } } } } //將棧中剩餘元素存入list while(!stack.isEmpty()) { pfixExpList.add(stack.pop()); } return pfixExpList; } /** * 得到表示式的最終值 * @param list 存放的字尾表示式各元素 * @return */ private static String getRes(List<String> list) { Stack<String> stack = new Stack<String>();//存放結果用 for(int i=0; i<list.size(); i++) { String el = list.get(i); if(el.matches("[0-9]*")) {//若為數字,直接入棧。 stack.push(el); } else {//若不為數字,則取出棧頂的兩個元素做運算,並將結果入棧 int v1 = 0; int v2 = 0; int res = 0; switch(el) { case "+": v2 = Integer.valueOf(stack.pop()); v1 = Integer.valueOf(stack.pop()); res = (v1 + v2); stack.push(res+""); break; case "-": v2 = Integer.valueOf(stack.pop()); v1 = Integer.valueOf(stack.pop()); res = (v1 - v2); stack.push(res+""); break; case "*": v2 = Integer.valueOf(stack.pop()); v1 = Integer.valueOf(stack.pop()); res = (v1 * v2); stack.push(res+""); break; case "/": v2 = Integer.valueOf(stack.pop()); v1 = Integer.valueOf(stack.pop()); res = (v1 / v2); stack.push(res+""); break; } } } return stack.pop(); } }
執行結果如下:
最終結果為:-131
注:關於這程式碼還有一個問題就是當表示式中有乘和除連續的時候,是按照其出現的順序計算的,這會導致1/3*3為0的情況。