1


import java.math.BigDecimal;
import java.util.*;

/**
 * 简单的公式计算工具,仅支持+ 、-、*、/、()
 * @author ningyongli
 * @date 2020-07-13
 */
public class CalculateUtils {

    private static final Map<String, Integer> PRIORITY_MAP = new HashMap<>();
    private static final List<String> OPERATOR_LIST = new ArrayList<>();

    static {

        PRIORITY_MAP.put("(", 0);
        PRIORITY_MAP.put("+", 5);
        PRIORITY_MAP.put("-", 5);
        PRIORITY_MAP.put("*", 10);
        PRIORITY_MAP.put("/", 10);
        PRIORITY_MAP.put(")", 15);

        OPERATOR_LIST.add("+");
        OPERATOR_LIST.add("-");
        OPERATOR_LIST.add("*");
        OPERATOR_LIST.add("/");
        OPERATOR_LIST.add("(");
        OPERATOR_LIST.add(")");

    }

    /**
     * 计算入口,除法计算小数位为16位
     * @param data 数据
     * @param express 公式
     * @return  BigDecimal 计算结果
     */
    public static String execute(Map<String, String> data, String express) {

        express = express.replaceAll("\\s", "");
        List<String> expressWordArr = split(express);
        Stack<String> dataStack = new Stack<>();
        Stack<String> operatorStact = new Stack<>();

        for (String expressWord : expressWordArr) {

            if (!OPERATOR_LIST.contains(expressWord)) {
                dataStack.push(expressWord);
            } else {
                if (operatorStact.isEmpty()) {
                    operatorStact.push(expressWord);
                } else {

                    if ("(".equals(expressWord)) {
                        operatorStact.push(expressWord);
                    } else if (")".equals(expressWord)) {
                        // 括号内计算;
                        operatorStact.push(expressWord);
                        dalRightBracket(dataStack, operatorStact, data);
                    } else {
                        // 加减乘除
                        calculate(dataStack, operatorStact, expressWord, data);
                    }
                }
            }
        }


        while (!operatorStact.empty()) {
            String operator = operatorStact.pop();
            dal(dataStack, operator, data);
        }

        return data.get(dataStack.pop());
    }

    /**
     * 解析关键词
     * @param express 公式
     * @return List<String> 拆分后的公式
     */
    private static List<String> split(String express) {

        List<String> list = new ArrayList<>();
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < express.length(); i++) {

            char c = express.charAt(i);
            if (!OPERATOR_LIST.contains(String.valueOf(c))) {
                builder.append(c);
            } else {
                list.add(builder.toString());
                builder.delete(0, builder.length());
                list.add(String.valueOf(c));
            }

            if (i == (express.length() - 1)) {
                if (builder.length() > 0) {
                    list.add(builder.toString());
                }
            }
        }

        return list;
    }

    /**
     * 括号内计算
     * @param dataStack 数据栈
     * @param operatorStact 操作栈
     * @param s 操作符
     * @param data 数据
     */
    private static void calculate(Stack<String> dataStack, Stack<String> operatorStact, String s, Map<String, String> data) {

        String oldOp = operatorStact.peek();
        int oldOpNum = PRIORITY_MAP.get(oldOp);
        int currentNum = PRIORITY_MAP.get(s);

        if (oldOpNum >= currentNum) {

            dal(dataStack, oldOp, data);
            operatorStact.pop();
            if (operatorStact.isEmpty()) {
                operatorStact.push(s);
            } else {
                calculate(dataStack, operatorStact, s, data);
            }
        } else {
            operatorStact.push(s);
        }
    }


    /**
     * 括号内计算
     * @param dataStack 数据栈
     * @param operatorStact 操作栈
     * @param data 数据
     */
    private static void dalRightBracket(Stack<String> dataStack, Stack<String> operatorStact, Map<String, String> data) {


        while ( !operatorStact.empty() && ")".equals(operatorStact.peek())) {
            String rightBracket = operatorStact.pop();
            String tempOp = operatorStact.peek();

            if ("(".equals(tempOp)) {
                operatorStact.pop();
            } else {
                dal(dataStack, tempOp, data);
                operatorStact.pop();
                operatorStact.push(rightBracket);
            }
        }
    }

    /**
     * 基础计算
     * @param dataStack 数据栈
     * @param operator 操作符
     * @param data 数据
     */
    private static void dal(Stack<String> dataStack, String operator, Map<String, String> data) {

        String temp = dataStack.pop();
        String oldTemp = dataStack.pop();
        BigDecimal tempValue;

        BigDecimal tempBigDecimal = new BigDecimal(data.get(temp));
        BigDecimal oldTempBigDecimal = new BigDecimal(data.get(oldTemp));

        switch (operator) {
            case "+":
                tempValue = oldTempBigDecimal.add(tempBigDecimal);
                break;
            case "-":
                tempValue = oldTempBigDecimal.subtract(tempBigDecimal);
                break;
            case "*":
                tempValue = oldTempBigDecimal.multiply(tempBigDecimal);
                break;
            case "/":
                tempValue = oldTempBigDecimal.divide(tempBigDecimal, 16, BigDecimal.ROUND_HALF_UP);
                break;
            default:
                throw new BaseRunTimeException("不支持的计算操作");
        }

        String uuid = String.valueOf(UUID.randomUUID());
        data.put("tempValue-" + uuid, tempValue.toString());
        dataStack.push("tempValue-" + uuid);

    }
}

一个简单的公式计算,有需要的可以参考一下


流浪的神明
226 声望9 粉丝

« 上一篇
mysql 索引学习