• 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;
        }
    
    
    }
    

      

  • 相关阅读:
    本周学习小结(04/11
    学习笔记之知识图谱 (Knowledge Graph)
    本周学习小结(28/10
    本周学习小结(21/10
    条件分页 代替离线查询
    Apache POI 一键上传(导入excel文件到数据库)
    easyui 菜单按钮&提示框
    Jquery ztree树插件
    Jquery ztree树插件2
    ui
  • 原文地址:https://www.cnblogs.com/zzllx/p/10283904.html
Copyright © 2020-2023  润新知