随记——逻辑运算小工具

逻辑运算小工具

  • 只支持逻辑运算
  • 中缀表达式转后缀表达式
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.sun.org.apache.xalan.internal.xsltc.compiler.util.StringStack;

import java.util.*;

/**
 * 公式计算类  使用公式进行逻辑运算
 */
public class Formula {
    /**
     * 使用空格分隔
     */
    private final static String SPLIT_FLAG = " ";

    /**
     * 只支持逻辑运算
     * @param expression 运算表达式
     * @return 返回 true or false  如果计算出错直接抛异常  注意捕获异常自己处理失败逻辑,失败请仔细检查表达式
     */
    public static boolean doExpression(String expression) {
        Queue<String> postfixEx = getPostfixEx(expression);
        /**
         * 操作数栈
         */
        Stack<Object> operandStack = new Stack<>();
        while (!postfixEx.isEmpty()) {
            String topOp = postfixEx.poll();
            if (Operator.MAP.containsKey(topOp)) {
                //是运算符
                if (Operator.NOT.equals(topOp)) {
                    boolean pop = (boolean) operandStack.pop();
                    operandStack.push(!pop);
                } else if (Arrays.asList(Operator.AND, Operator.OR).contains(topOp)) {
                    boolean right = (boolean) operandStack.pop();
                    boolean left = (boolean) operandStack.pop();
                    if (Operator.AND.equals(topOp)) {
                        operandStack.push(left && right);
                    } else if (Operator.OR.equals(topOp)) {
                        operandStack.push(left || right);
                    }
                } else {
                    long right = Long.parseLong((String) operandStack.pop());
                    long left = Long.parseLong((String) operandStack.pop());
                    switch (topOp) {
                        case Operator.LT:
                            operandStack.push(left < right);
                            break;
                        case Operator.LE:
                            operandStack.push(left <= right);
                            break;
                        case Operator.GT:
                            operandStack.push(left > right);
                            break;
                        case Operator.GE:
                            operandStack.push(left >= right);
                            break;
                        case Operator.EQ:
                            operandStack.push(left == right);
                            break;
                        case Operator.NE:
                            operandStack.push(left != right);
                            break;
                        default:
                            //TODO 这个位置应该抛异常,在使用时自己修改
                            System.out.println("操作符不存在");
                    }
                }
            } else {
                //是操作数
                operandStack.push(topOp);
            }
        }
        return (boolean) operandStack.pop();
    }

    /**
     * 中缀表达式转后缀表达式
     * 1、操作数直接入队列
     * 2、左括号直接入运算符栈
     * 3、运算符
     *    如果运算符栈为空,入栈
     *    如果运算符优先级小于于栈顶运算符,栈顶出栈入队列,当前运算符入栈
     *    如果运算符优先级大于等于栈顶运算符,直接入栈
     * 4、右括号
     *    不入栈。将运算符栈出栈,入队列,直到遇到左括号,左括号出栈不入队列
     * 5、中缀表达式遍历结算,将操作数栈全部出栈,入队列
     * @param expression 表达式,要求:每个操作数和操作符之间用空格分隔 如:( 1  < 2 && ! ( 3 > 4 ) )
     * @return 后缀表达式队列
     */
    private static Queue<String> getPostfixEx(String expression) {
        /**
         * 后缀表达式
         */
        Queue<String> postfixEx = new LinkedList<>();
        /**
         * 运算符栈
         */
        StringStack operatorStack = new StringStack();
        String[] ops = expression.split(SPLIT_FLAG);
        for (String op : ops) {
            op = op.trim();
            if ("".equals(op)) {
                continue;
            }
            if (Operator.LEFT.equals(op)) {
                operatorStack.pushString(op);
            } else if (Operator.RIGHT.equals(op)) {
                while (!operatorStack.isEmpty() && !Operator.LEFT.equals(op = operatorStack.popString())) {
                    postfixEx.add(op);
                }
            } else if (Operator.MAP.containsKey(op)) {
                if (!operatorStack.isEmpty()) {
                    String topOp = operatorStack.peekString();
                    if (Operator.comparePri(op, topOp)) {
                        //运算符优先级小于栈顶运算符,出栈,新运算符进栈
                        postfixEx.add(operatorStack.popString());
                    }
                }
                operatorStack.pushString(op);
            } else {
                postfixEx.add(op);
            }
        }
        while (!operatorStack.isEmpty()) {
            postfixEx.add(operatorStack.popString());
        }

        /*while (!postfixEx.isEmpty()) {
            System.out.print(postfixEx.poll() + " ");
        }*/
        return postfixEx;
    }

    static class Operator {
        /**
         * 等于
         */
        private final static String EQ = "==";
        /**
         * 不等于
         */
        private final static String NE = "!=";
        /**
         * 大于
         */
        private final static String GT = ">";
        /**
         * 大于等于
         */
        private final static String GE = ">=";
        /**
         * 小于
         */
        private final static String LT = "<";
        /**
         * 小于等于
         */
        private final static String LE = "<=";
        /**
         * 左括号
         */
        private final static String LEFT = "(";
        /**
         * 右括号
         */
        private final static String RIGHT = ")";
        private final static String AND = "&&";
        private final static String OR = "||";
        private final static String NOT = "!";

        /**
         * 优先级
         */
        private final static int PRIORITY_0 = 0;
        private final static int PRIORITY_1 = 1;
        private final static int PRIORITY_2 = 2;
        private final static int PRIORITY_3 = 3;
        private static final Map<String, Integer> MAP;

        static {
            MAP = new HashMap<>();
            MAP.put(GT, PRIORITY_2);
            MAP.put(LT, PRIORITY_2);
            MAP.put(EQ, PRIORITY_2);
            MAP.put(GE, PRIORITY_2);
            MAP.put(LE, PRIORITY_2);
            MAP.put(NE, PRIORITY_2);
            MAP.put(LEFT, PRIORITY_0);
            MAP.put(RIGHT, PRIORITY_3);
            MAP.put(AND, PRIORITY_1);
            MAP.put(OR, PRIORITY_1);
            MAP.put(NOT, PRIORITY_1);
        }

        /**
         * 获取优先级
         * @param op
         * @return
         */
        static int getPriority(String op) {
            return MAP.get(op);
        }

        /**
         * 比较优先级, 如果 op1 < op2 返回true
         * @param op1
         * @param op2
         * @return
         */
        static boolean comparePri(String op1, String op2) {
            if (MAP.get(op1) < MAP.get(op2)) {
                return true;
            }
            return false;
        }
    }

    public static void main(String[] args) {
        String rule = "{\n" +
                "\t\"large\": \"( income >= 20000 )\",\n" +
                "\t\"medium\": \"( income < 20000 && income >= 500 )\",\n" +
                "\t\"small\": \"( income < 500 && income >= 50 )\",\n" +
                "\t\"micro\": \"( income < 50 )\"\n" +
                "}";

        String rule1 = "{\n" +
                "\t\"large\": \"( employee >= 1000 || income >= 40000 )\",\n" +
                "\t\"medium\": \"( ( employee < 1000 || income < 40000 ) && employee >= 300 && income >= 2000 )\",\n" +
                "\t\"small\": \"( ( employee < 300 || income < 2000 ) && employee >= 20 && income >= 300 )\",\n" +
                "\t\"micro\": \"( employee < 20 || income < 300 )\"\n" +
                "}";
        String enterpriseSize = "medium";
        Map<String, String> map = new HashMap<>();
        map.put("employee", "300");
        map.put("income", "2000");
        map.put("capital", "100");
        JSONObject ruleJson = JSONUtil.parseObj(rule1);
        String expression = ruleJson.getStr(enterpriseSize);
        for (String key : map.keySet()) {
            expression = expression.replace(key, map.get(key));
        }
        System.out.println(Formula.doExpression(expression));
    }
}


  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值