栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

java实现加减乘除以及等式判断

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

java实现加减乘除以及等式判断

做excel单元格自定义校验规则时搞的一个小轮子,适合给不懂编码的人使用,如果会一些编码知识,直接使用groovy解析会更灵活。

可稍作拆解为计算器。

package com.weilink.commontools.utils.calculator;

import java.math.BigDecimal;


public class Mycalculator {

    public static void main(String[] args) throws Exception {
        System.out.println(explainExpress("MIN(3*4/6+MAX(3,4),2)=2"));
    }

    // 长的放在数组前面,因为在匹配表达式时优先匹配长的
    private static String[] validSymbol = new String[]{">=", "<=", "!=", "≥", "≤", "≠", ">", "<", "="};


    public static boolean explainExpress(String str) throws Exception {
        return explainExpress(str, null).equals("true");
    }

    private static String explainExpress(String str, Function function) throws Exception {
        str = str.replaceAll(" ", "");

        if (null != function) {
            return function.cal();
        }
        // 函数优先计算
        str = functionCal(str);

        // 递归计算

        // 括号优先
        if (str.contains(")")) {
            int lIndex = str.lastIndexOf("(");
            int rIndex = str.indexOf(")", lIndex);
            return explainExpress(str.substring(0, lIndex) + explainExpress(str.substring(lIndex + 1, rIndex), null) + str.substring(rIndex + 1), null);
        }

        if (str.contains("|")) {
            int index = str.lastIndexOf("|");
            String valLeft = explainExpress(str.substring(0, index), null);
            String valRight = explainExpress(str.substring(index + 1), null);
            if (valLeft.equals("true") || valRight.equals("true")) {
                return "true";
            } else {
                return "false";
            }
        }


        if (str.contains("&")) {
            int index = str.lastIndexOf("&");
            String valLeft = explainExpress(str.substring(0, index), null);
            String valRight = explainExpress(str.substring(index + 1), null);
            if (valLeft.equals("true") && valRight.equals("true")) {
                return "true";
            } else {
                return "false";
            }
        }

        return expressValid(str);
    }

    private static String expressValid(String exp) throws Exception {
        if (exp.equals("true")) {
            return "true";
        } else if (exp.equals("false")) {
            return "false";
        }
        String symbol = null;
        String[] formulas = null;
        for (String sy : validSymbol) {
            if (exp.split(sy).length == 2) {
                symbol = sy;
                formulas = exp.split(sy);
                break;
            }
        }

        if (formulas == null) {
            return getResult(exp).toPlainString();
        }
        BigDecimal valueLeft = getResult(formulas[0]);
        BigDecimal valueRight = getResult(formulas[1]);
        switch (symbol) {
            case ">":
                return valueLeft.compareTo(valueRight) > 0 ? "true" : "false";
            case "<":
                return valueLeft.compareTo(valueRight) < 0 ? "true" : "false";
            case "=":
                // 默认等于的精度为四位
                return valueLeft.subtract(valueRight).abs().compareTo(new BigDecimal("0.0001")) < 0 ? "true" : "false";
            case "≥":
                return valueLeft.compareTo(valueRight) >= 0 ? "true" : "false";
            case ">=":
                return valueLeft.compareTo(valueRight) >= 0 ? "true" : "false";
            case "≤":
                return valueLeft.compareTo(valueRight) <= 0 ? "true" : "false";
            case "<=":
                return valueLeft.compareTo(valueRight) <= 0 ? "true" : "false";

            case "≠":
                return valueLeft.compareTo(valueRight) != 0 ? "true" : "false";
            case "!=":
                return valueLeft.compareTo(valueRight) != 0 ? "true" : "false";

        }
        throw new Exception("错误的表达式");


    }

    private static String functionCal(String str) throws Exception {
        // 这里设计的有问题,应该把所有函数设置为static数组变量放到Function中,判断最右侧变量的逻辑也
        // 该相应改造
        
        while (str.contains("MAX") || str.contains("MIN")) {
            Function function;
            int start = 0;
            int startMin = str.indexOf("(", str.lastIndexOf("MIN"));
            int startMax = str.indexOf("(", str.lastIndexOf("MAX"));
            if (str.lastIndexOf("MIN") < 0) {
                start = startMax;
                function = new Max();
            } else if (str.lastIndexOf("MAX") < 0) {
                start = startMin;
                function = new Min();
            } else {
                if (startMax > startMin) {
                    start = startMax;
                    function = new Max();
                } else {
                    start = startMin;
                    function = new Min();
                }

            }

            int end = getEnd(str, start);
            String innerExpr = str.substring(start + 1, end);
            function.setExpr(innerExpr);
            String startStr = str.substring(0, start - 3);
            String endStr = str.substring(end + 1);
            str = startStr + explainExpress(str, function) + endStr;
        }
        return str;
    }

    private static int getEnd(String str, int start) throws Exception {
        int count = 1;
        for (int i = start + 1; i < str.length(); i++) {
            if (str.charAt(i) == '(') {
                count++;
            }

            if (str.charAt(i) == ')') {
                count--;
            }

            if (count == 0) {
                return i;
            }

        }
        throw new Exception("错误的表达式");
    }

    public static BigDecimal getResult(String str) throws Exception {
        if (str.isEmpty() || isNumber(str)) {
            if (str.isEmpty()) {
                return BigDecimal.ZERO;
            }

            if (str.endsWith("%")) {
                str = str.replace("%", "");
                return new BigDecimal(str).divide(new BigDecimal("100"));
            }
            return new BigDecimal(str);
        }

        if (str.contains(")")) {
            int lIndex = str.lastIndexOf("(");
            int rIndex = str.indexOf(")", lIndex);
            return getResult(str.substring(0, lIndex) + getResult(str.substring(lIndex + 1, rIndex)) + str.substring(rIndex + 1));
        }

        //先乘除后加减
        //乘除运算必须从左边算起

        if (str.contains("*") || str.contains("/")) {
            int locate;
            int locateM = str.indexOf("*");
            int loacateD = str.indexOf("/");
            int type = 1;
            if (loacateD < 0) {
                locate = locateM;
            } else if (locateM < 0) {
                locate = loacateD;
                type = 2;
            } else {
                if (locateM < loacateD) {
                    locate = locateM;
                } else {
                    locate = loacateD;
                    type = 2;
                }
            }
            int leftNum = getLeftNum(str, locate);
            int rightNum = getRightNum(str, locate);
            BigDecimal leftValue = new BigDecimal(str.substring(leftNum, locate));
            BigDecimal rightValue;

            String leftStr = str.substring(0, leftNum);
            String rightStr;
            if (rightNum >= str.length()) {
                rightValue = new BigDecimal(str.substring(locate + 1));
                rightStr = "";
            } else {
                rightStr = str.substring(rightNum + 1);
                rightValue = new BigDecimal(str.substring(locate + 1, rightNum + 1));
            }

            String value;
            if (type == 1) {
                value = leftValue.multiply(rightValue).toPlainString();
            } else {
                value = leftValue.divide(rightValue, 10, BigDecimal.ROUND_DOWN).toPlainString();
            }
            return getResult(leftStr + value + rightStr);

        }

        if (str.contains("+")) {
            int index = str.lastIndexOf("+");
            return getResult(str.substring(0, index)).add(getResult(str.substring(index + 1)));
        }

        if (str.contains("-")) {
            int index = str.lastIndexOf("-");
            return getResult(str.substring(0, index)).subtract(getResult(str.substring(index + 1)));
        }

        throw new Exception("错误的表达式");
    }

    private static int getLeftNum(String str, int locate) {
        for (int i = locate - 1; i >= 0; i--) {
            if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != '%') {
                return i + 1;
            }
        }
        return 0;
    }

    private static int getRightNum(String str, int locate) {
        for (int i = locate + 1; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != '%') {
                return i - 1;
            }
        }
        return str.length();
    }

    static boolean isNumber(String str) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != '%') {
                return false;
            }
        }
        return true;
    }
}

几个扩展类

package com.weilink.commontools.utils.calculator;


public abstract class Function {

    protected String expr;

    public Function(String expr) {
        this.expr = expr;
    }

    public Function() {

    }

    public abstract String cal()throws Exception;

    public String getExpr() {
        return expr;
    }

    public void setExpr(String expr) {
        this.expr = expr;
    }
}

package com.weilink.commontools.utils.calculator;

import java.math.BigDecimal;


public class Max extends Function {
    @Override
    public String cal() throws Exception{
        BigDecimal val = null;
        for (String str : expr.split(",")) {
            BigDecimal current = Mycalculator.getResult(str);
            if (val == null || val.compareTo(current) < 0) {
                val = current;
            }
        }
        return val.toPlainString();
    }
}
package com.weilink.commontools.utils.calculator;

import java.math.BigDecimal;


public class Min extends Function {
    @Override
    public String cal() throws Exception{
        BigDecimal val = null;
        for (String str : expr.split(",")) {
            BigDecimal current = Mycalculator.getResult(str);
            if (val == null || val.compareTo(current) > 0) {
                val = current;
            }
        }
        return val.toPlainString();
    }
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/306808.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号