java 计算器后台实现
有两种方案,第一种想到了就很简单,调用js脚本
public class CalculatorByJavaScript { public static void main(String[] args) { String str = "15*7-(19-18*(11+12))"; //执行JS脚本 ScriptEngine jse = new ScriptEngineManager().getEngineByName("JavaScript"); Object eval; try { eval = jse.eval(str); System.out.println(eval); if("Infinity".equals(eval.toString())) { throw new RuntimeException("分母不能为0"); } } catch (Exception e) { if(e instanceof javax.script.ScriptException) { System.out.println(String.format("%s:表达式错误 %n %s" ,str,e.getMessage())); }else { System.out.println(e.getMessage()); } e.printStackTrace(); } } }
第二种就是用栈来实现,难点在于表达式中负数的截取:比如3+(-11),(-11)+3
还有就是对 后缀表达式,中缀表达式的理解(不明白的,百度一下)
package com.zh.javaweb.calculator; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Scanner; import java.util.Stack; import org.springframework.util.NumberUtils; /** * @author zhouhong * @createDate 2019年1月17日 下午12:10:58 */ public class CalculatorByJava { @SuppressWarnings("resource") public static void main(String[] args) { Scanner scan = new Scanner(System.in); while (true) { String mid = scan.nextLine(); if (mid.equals("")) { System.out.println("已结束输入!"); break; } List<String> list = transferToBehind(mid); BigDecimal comeOut = calculator(list); System.out.println(comeOut); } } /** * 将表达式分割,eg:2+66*2 1,+,*,2 * @author: zhouhong * @date: 2019年1月17日 下午12:24:30 * @param mid * @return */ private static List<String> transferToBehind(String mid) { //去除前后空格 char[] charArray = mid.trim().toCharArray(); //解析字符数组 String str = transferToStr(charArray); return transferToList(str); } /** * 把带有1,2+3,,0,-1 字符串转换成 list 去掉中间的空格 * @author: zhouhong * @date: 2019年1月17日 下午2:23:29 * @param str * @return */ private static List<String> transferToList(String str) { String[] split = str.split(","); List<String> asList = new ArrayList<>(Arrays.asList(split)); Iterator<String> iterator = asList.iterator(); while (iterator.hasNext()) { String next = iterator.next(); if (next == null || " ".equals(next) || "".equals(next)) { iterator.remove(); } } return asList; } /** * * @author: zhouhong * @date: 2019年1月17日 下午2:17:34 * @param charArray * @return */ private static String transferToStr(char[] charArray) { String str = ""; for (int i = 0; i < charArray.length; i++) { char c = charArray[i]; if (i == 0 && checkNumber(c)) {//判断首位是数字 str = str + c; continue; } if (i == 0 && "-".equals(String.valueOf(c))) {//判断首位是负数- str = str + "," + c; continue; } if ("(".equals(String.valueOf(c)) || ")".equals(String.valueOf(c))) {//判断是否是括号 str = str + "," + c + ","; continue; } if ("(".equals(String.valueOf(charArray[i - 1])) && checkSymbol(c)) {//判断左括号后面是符号比如(-1) (- str = str + "," + c+charArray[i=i + 1]; continue; } if ("(".equals(String.valueOf(charArray[i - 1])) && checkNumber(c)) {//判断左括号后面是否是数字比如(1) (1 if(checkNumber(charArray[i +1])) { str = str + "," + c + charArray[i=i + 1]; }else { str = str + "," + c + ","; } continue; } if (checkSymbol(c)) { str = str + "," + c + ","; } if (checkNumber(c)) { str += c; } } return str; } private static BigDecimal calculator(List<String> list) { Stack<String> s1 = new Stack<String>();//用于计算 --后缀表达式 Stack<String> s2 = new Stack<String>();//出栈 pushStack(list, s1); popStack(s1,s2); return new BigDecimal(s2.pop()); } private static void popStack(Stack<String> s1, Stack<String> s2) { //[9, 3, 1, -, 3, *, +, 10, 2, /, +] Stack<String> temp = new Stack<String>(); while(!s1.empty()) { temp.push(s1.pop()); } while(!temp.empty()) { if (checkNumber(temp.peek())) { //检查数字 s2.push(temp.pop()); continue; } BigDecimal num1 = new BigDecimal(s2.pop()); BigDecimal num2 = new BigDecimal(s2.pop()); switch (temp.pop()) { case "+": BigDecimal add = num2.add(num1); s2.push(String.valueOf(add.intValue())); break; case "-": BigDecimal subtract = num2.subtract(num1); s2.push(String.valueOf(subtract.intValue())); break; case "*": BigDecimal multiply = num2.multiply(num1); s2.push(String.valueOf(multiply.intValue())); break; case "/": BigDecimal divide = num2.divide(num1); s2.push(String.valueOf(divide.intValue())); break; default: break; } } } private static void pushStack(List<String> list, Stack<String> s1) { Stack<SymbolEnum> s2 = new Stack<SymbolEnum>();//临时存放运算符 -- 中缀 for (String str : list) { pushStack(str,s1,s2); } while(!s2.isEmpty()) { s1.push(s2.pop().getType()); } } private static void pushStack(String str, Stack<String> s1, Stack<SymbolEnum> s2) { if (checkNumber(str)) { //检查数字 s1.push(str); return; } if ("(".equals(str)) {//检查左括号 s2.push(SymbolEnum.getValue(str)); return; } if (checkSymbol(str.toCharArray()[0])) { //检查运算符 SymbolEnum symbol1 = SymbolEnum.getValue(str); if (s2.empty()) { s2.push(symbol1); }else { SymbolEnum symbol2 = s2.peek(); if(symbol2.getNum() < 4 ) { while(!s2.empty() && symbol1.getNum() <=s2.peek().getNum() ) { s1.push(s2.pop().getType()); } } s2.push(symbol1); } } if (")".equals(str)) {//检查右括号 while(!s2.peek().getType().equals("(") ) { s1.push(s2.pop().getType()); } s2.pop();//删除左括号 } } /** * 判断是否是运算符 + - * / * @author: zhouhong * @date: 2019年1月17日 上午1:34:06 * @param word * @return */ public static boolean checkSymbol(char word) { if (word == '+' || word == '-' || word == '*' || word == '/') { return true; } return false; } /** * 判断数字 * @author: zhouhong * @date: 2019年1月17日 上午1:35:58 * @param word * @return */ public static boolean checkNumber(char word) { if ((word >= '0' && word <= '9') || word == '.') { return true; } return false; } public static boolean checkNumber(String word) { try { NumberUtils.parseNumber(word, BigDecimal.class); return true; }catch(Exception e) { return false; } } } enum SymbolEnum { RIGHT_BRACKETS(")", 8), LEFT_BRACKETS("(",4), MULTIPLY("*",2), EXCEPT("/", 2), ADD("+",1), REDUCE("-",1),; String type; int num; public static SymbolEnum getValue(String type) { for (SymbolEnum symbol : SymbolEnum.values()) { if(symbol.getType().equals(type)) { return symbol; } } return null; } public static SymbolEnum getValue(int num) { for (SymbolEnum symbol : SymbolEnum.values()) { if(symbol.getNum() == num) { return symbol; } } return null; } private SymbolEnum(String type, int num) { this.type = type; this.num = num; } public String getType() { return type; } public int getNum() { return num; } }