zoukankan      html  css  js  c++  java
  • Java解析表达式

    需求

    指定一个String表达式,表达式符合给出的运算符规范,比如:2!=2 and 2>=3 or 4<=4,计算出表达式的结果(true or false)。 支持的操作符:(,),and,or,mod,+,-,*,/,>,>=,<,<=,=,!=

    思路

    1. 首先要用Java运算符替换表达式中的部分操作符,如and替换为&&,or替换为||,具体如下: ``` operatorsMap.put("\s+and\s+", "&&"); operatorsMap.put("\s+or\s+", "||"); operatorsMap.put("\s+mod\s+", "%"); operatorsMap.put("(?|<|\!|=)=(?!=|>|<|\!)", "=="); operatorsMap.put("\)and\s+", ")&&"); operatorsMap.put("\s+and\(", "&&("); operatorsMap.put("\)and\(", ")&&("); operatorsMap.put("\)or\s+", ")||"); operatorsMap.put("\s+or\(", "||("); operatorsMap.put("\)or\(", ")||("); operatorsMap.put("\)mod\s+", ")%"); operatorsMap.put("\s+mod\(", "%("); operatorsMap.put("\)mod\(", ")%("); operatorsMap.put("\!\s+\=", "!="); operatorsMap.put("\>\s+\=", ">="); operatorsMap.put("\<\s+\=", "<="); ``` 2. 将替换后的表达式,转化了一个```List```,Segment定义为: ```java public Segment(String word,int type){ this.word = word;//词 this.type = type;//类型,如DIGIT = 1;LETTER = 2; } ``` 比如(ab+cd)/2 >= 3,解析后的Segment列表为: ``` segment1: ( segment2: ab segment3: + segment4: cd segment5: ) segment6: / segment7: 2 segment8: space segment9: >= segment10: space segment11: 3 ``` 3. 将```List```转化为后缀表达式```List```,其中过滤掉空格(space)```Segment``` ```java public void doConvert(Segment segment) { int type = segment.getType(); if (isBarcket(type)) { //括号的处理 dealBracket(segment); } else if (isOperator(type)) { dealOperator(segment);//运算符的处理 } else { list.add(segment.getWord());//操作数的处理 } } ``` 4. 自定义各种运算符的计算规则 ```java operationMap.put("+", new PlusOperator()); operationMap.put("-", new MinusOperator()); operationMap.put("*", new MultipliedOperator()); operationMap.put("/", new DivideOperator()); operationMap.put("%", new ModOperator()); operationMap.put("^", new PowerOperator()); operationMap.put(">", new GtOperator()); operationMap.put("<", new LtOperator()); operationMap.put(">=", new GeOperator()); operationMap.put("<=", new LeOperator()); operationMap.put("==", new EqOperator()); operationMap.put("!=", new NeOperator()); operationMap.put("&&", new AndOperator()); operationMap.put("||", new OrOperator());
        //比如加法运算符,PlusOperator:
        public void operator(Deque<String> stack) {
            //操作数出栈,完成运算
                BigDecimal b = new BigDecimal(stack.pop());
                BigDecimal a = new BigDecimal(stack.pop());
                stack.push(a.add(b).stripTrailingZeros().toPlainString());
            }
    
    
    5. 计算后缀表达式的值。如果后缀表达式中操作数都是变量名,那么计算之前需要完成值的替换。
    ```java
    public String compute(List<String> postfix) {
            try {
                Deque<String> stack = new ArrayDeque<>();
                for (String item : postfix) {
                    Operator op = operationMap.get(item);
                    if (null == op) {
                        stack.push(item);
                    } else {
                        op.operator(stack);
                    }
                }
                return stack.pop();
            } catch (Exception e) {
                logger.info(e.getMessage(), e);
                return "ERROR";
            }
        }
    
    1. 返回布尔值
    //List<String> mustList后缀表达式
    //Map<String, Object> value表达式中变量的值
    public boolean getResult(List<String> mustList, Map<String, Object> value) {
            return Boolean.parseBoolean(compute(replace(mustList, value)));
        }
    

    总结

    将表达式处理为后缀表达式,通过栈完成操作数的运算,是个比较经典的小程序,比较考验计算机功底和细节处理。
  • 相关阅读:
    V2EX 上收藏Top200
    在heroku上部署gost代理服务端
    nano编辑器使用教程
    Amazon EC2免费VPS防止超额被扣钱三大方法:流量 硬盘读写 运行时长
    Go语言开发环境配置
    HTML5 and CSS3 开发
    使用 Eclipse PhoneGap 构建 Android 应用程序入门
    脚本之家
    CSS网页布局全精通
    使用面向 iOS 的本机插件扩展 PhoneGap
  • 原文地址:https://www.cnblogs.com/lknny/p/7509953.html
Copyright © 2011-2022 走看看