zoukankan      html  css  js  c++  java
  • java 解析四则混合运算表达式并计算结果

    1. package ch8;
    2. import java.util.LinkedList;
    3. import java.util.List;
    4. import java.util.Stack;
    5. /**
    6. * 四则混合运算表达式计算
    7. * @author Jinjichao
    8. *
    9. */
    10. public class Calculator {
    11.     /**
    12.      * 运算符枚举
    13.      * @author Jinjichao
    14.      *
    15.      */
    16.     private enum Operator {
    17.         ADD("+", 10), SUBTRACT("-", 10), MULTIPLY("*", 20), DIVIDE("/", 20),
    18.         PARENTHESIS_LEFT("(", 100), PARENTHESIS_RIGHT(")", 100);
    19.         private String operator;
    20.         private int priority;
    21.         private Operator(String operator, int priority) {
    22.             this.operator = operator;
    23.             this.priority = priority;
    24.         }
    25.     }
    26.     /**
    27.      * 操作数枚举
    28.      * @author Jinjichao
    29.      *
    30.      */
    31.     private enum Operand {
    32.         ONE("1"), TWO("2"), THREE("3"), FOUR("4"), FIVE("5"), SIX("6"),
    33.         SEVEN("7"), EIGHT("8"), NINE("9"), ZERO("0"), POINT(".");
    34.         private String operand;
    35.         private Operand(String operand) {
    36.             this.operand = operand;
    37.         }
    38.     }
    39.    
    40.     /**
    41.      * 获取字符串所对应的运算符枚举
    42.      * @param str
    43.      * @return
    44.      */
    45.     private Operator getOperator(String str) {
    46.         for (Operator op : Operator.values()) {
    47.             if (str.equals(op.operator)) {
    48.                 return op;
    49.             }
    50.         }
    51.         return null;
    52.     }
    53.     /**
    54.      * 获取字符串所对应的操作数枚举
    55.      * @param str
    56.      * @return
    57.      */
    58.     private Operand getOperand(String str) {
    59.         for (Operand op : Operand.values()) {
    60.             if (str.equals(op.operand)) {
    61.                 return op;
    62.             }
    63.         }
    64.         return null;
    65.     }   
    66.     /**
    67.      * 第1步: 将运算表达式字符串分解为运算表达式List
    68.      *
    69.      * @param exp
    70.      * @return
    71.      */
    72.     private List<String> resolveExpr(String exp) {
    73.         List<String> list = new LinkedList<String>();
    74.         String temp = "";
    75.         exp = exp.replace(" ", "");
    76.         for (int i = 0; i < exp.length(); i++) {
    77.             String str = exp.substring(i, i + 1);
    78.             Operator op = getOperator(str);
    79.             Operand od = getOperand(str);
    80.             if (op != null) {
    81.                 if (!temp.isEmpty()) {
    82.                     list.add(temp);
    83.                     temp = "";
    84.                 }
    85.                 list.add(str);
    86.             } else if (od != null) {
    87.                 temp += str;
    88.             } else {
    89.                 System.out.println("表达式[" + str + "]非法! ");
    90.                 return null;
    91.             }
    92.         }
    93.         if (!temp.isEmpty()) {
    94.             list.add(temp);
    95.         }
    96.         //System.out.println(list);
    97.         return list;
    98.     }
    99.     /**
    100.      * 第2步: 将运算表达式List转换为逆波兰表达式List
    101.      * @param expList
    102.      * @return
    103.      */
    104.     private List<String> dealExpr(List<String> expList) {
    105.         if(expList == null) {
    106.             return null;
    107.         }
    108.         
    109.         List<String> list = new LinkedList<String>();
    110.         Stack<String> stack = new Stack<String>();
    111.         for (String str : expList) {
    112.             Operator op = getOperator(str.substring(0, 1));
    113.             Operand od = getOperand(str.substring(0, 1));
    114.             if (od != null) {
    115.                 //操作数直接入队列
    116.                 list.add(str);
    117.             } else if (op != null) {
    118.                 if (Operator.PARENTHESIS_LEFT.equals(op)) {
    119.                     //左括号入栈
    120.                     stack.push(str);
    121.                 } else if (Operator.PARENTHESIS_RIGHT.equals(op)) {
    122.                     //右括号: 循环将栈顶的运算符取出并存入队列,直到取出左括号
    123.                     while (true) {
    124.                         if (stack.empty()) {
    125.                             System.out.println("缺少左括号! ");
    126.                             return null;
    127.                         } else if (Operator.PARENTHESIS_LEFT.operator.equals(stack.peek())) {
    128.                             stack.pop();
    129.                             break;
    130.                         } else {
    131.                             list.add(stack.pop());
    132.                         }
    133.                     }
    134.                 } else {
    135.                     //非括号类运算符
    136.                     if (!stack.empty()) {
    137.                         Operator top_op = getOperator(stack.peek());
    138.                         //当前运算符优先级大于栈顶运算符优先级,或者栈顶为左括号时,当前运算符直接入栈
    139.                         if(op.priority > top_op.priority
    140.                                 || Operator.PARENTHESIS_LEFT.equals(top_op)) {
    141.                             stack.push(str);
    142.                         }
    143.                         //否则,将栈顶的运算符取出并存入队列,然后将自己入栈
    144.                         else {
    145.                             list.add(stack.pop());
    146.                             stack.push(str);
    147.                         }                        
    148.                     } else {
    149.                         stack.push(str);
    150.                     }
    151.                 }
    152.             }
    153.         }
    154.         while(!stack.empty()) {
    155.             String str = stack.peek();
    156.             if(Operator.PARENTHESIS_LEFT.operator.equals(str)) {
    157.                 System.out.println("缺少右括号! ");
    158.                 return null;
    159.             } else {
    160.                 list.add(stack.pop());
    161.             }
    162.         }
    163.         //System.out.println(list);
    164.         return list;
    165.     }
    166.    
    167.     /**
    168.      * 操作数运算
    169.      * @param x
    170.      * @param y
    171.      * @param op
    172.      * @return
    173.      */
    174.     private String operation(String x, String y, Operator op) {
    175.         double a = 0.0;
    176.         double b = 0.0;
    177.         try {
    178.             a = Double.parseDouble(x);
    179.             b = Double.parseDouble(y);
    180.         } catch (NumberFormatException e) {
    181.             System.out.println("操作数非法! ");
    182.             e.printStackTrace();
    183.         }
    184.         
    185.         switch (op) {
    186.         case ADD:
    187.             return String.valueOf(a + b);
    188.         case SUBTRACT:
    189.             return String.valueOf(a - b);
    190.         case MULTIPLY:
    191.             return String.valueOf(a * b);
    192.         case DIVIDE:
    193.             return String.valueOf(a / b);
    194.         default:
    195.             return null;
    196.         }
    197.     }
    198.    
    199.     /**
    200.      * 第3步: 逆波兰表达式运算
    201.      * @param exp
    202.      * @return
    203.      */
    204.     public String calculate(String exp) {
    205.         List<String> expList = dealExpr(resolveExpr(exp));
    206.         if(expList == null) {
    207.             return null;
    208.         }
    209.         Stack<String> stack = new Stack<String>();
    210.         for(String str : expList) {
    211.             Operator op = getOperator(str.substring(0, 1));
    212.             Operand od = getOperand(str.substring(0, 1));
    213.             if(od != null) {
    214.                 stack.push(str);
    215.             } else if (op != null) {
    216.                 //目前仅针对二元运算符
    217.                 String x = "";
    218.                 String y = "";
    219.                 if(!stack.empty()) {
    220.                     y = stack.pop();
    221.                 }
    222.                 if(!stack.empty()) {
    223.                     x = stack.pop();
    224.                 }               
    225.                 if(!x.isEmpty() && !x.isEmpty()) {
    226.                     String result = operation(x, y, op);
    227.                     if(result == null) {
    228.                         return null;
    229.                     }
    230.                     stack.push(result);
    231.                 } else {
    232.                     return null;
    233.                 }
    234.             }
    235.         }
    236.         return stack.pop();
    237.     }   
    238. }
    复制代码



    测试一下:

    1. package ch8;
    2. /**
    3. * 测试
    4. * @author Jinjichao
    5. *
    6. */
    7. public class Test {
    8.     public static void main(String[] args) {
    9.         Calculator cal = new Calculator();
    10.         String str = cal.calculate("( ( ( 15 / 3 ) + ( 1.5 * 2 ) + ( 20 - 12 ))  - 3.2 +2.3 + 5 ) ");
    11.         System.out.println("运算结果:" + str);
    12.     }
    13. }
    复制代码


    运行结果:
    运算结果:20.1
    其他的测试案例:

    <IGNORE_JS_OP>



    <IGNORE_JS_OP>



    <IGNORE_JS_OP>




    算法原理(对照截图):
    第1步、将表达式字符串分解为运算表达式List(将运算符和操作数分别分解出来)
    第2步:将运算表达式List转换为逆波兰表达式List

    第3步:逆波兰表达式运算

  • 相关阅读:
    发球
    Java学习笔记
    驼峰式命名法
    公式编辑测试
    Python3.5 在Ubuntu16.04上无法画图的解决方案
    Ubuntu16.04 安装flash player
    Spring切面通知执行的顺序(Advice Order)
    修改别人写的利用AOP实现日志监控的问题
    传感器系列之4.10 酒精传感器
    传感器系列之4.8光敏传感器
  • 原文地址:https://www.cnblogs.com/firstdream/p/5649655.html
Copyright © 2011-2022 走看看