java实现算术表达式(+、-、*、/、%、!、^、||、sin、cos、tan、cot、lg、ln等)

    /**
     * 计算表达式
     * 支持 +、-、*、/、%、^、!、||、sin、cos、tan、cot、lg、ln等
     * 支持值π、e
     * @param ariStr
     * @return
     * @throws Exception
     */
    public static double arith(String ariStr) throws Exception{
        int lBracket = ariStr.indexOf('(');
        if(lBracket < 0){
            return arithContainAbs(ariStr);
        }
        int rBracket = matchedRBracket(ariStr);
        String start = ariStr.substring(0, lBracket);
        String middle = ariStr.substring(lBracket + 1, rBracket);
        String end = ariStr.substring(rBracket + 1);
        return arith(start + arith(middle) + end);
    }

    /**
     * 包含||
     * @param str
     * @return
     * @throws Exception 
     */
    public static double arithContainAbs(String str) throws Exception{
        int lAbs = str.indexOf("|");
        if(lAbs < 0){
            return simpleArith(str);
        }
        int rAbs = matchedRAbs(str);
        String start = str.substring(0, lAbs);
        String middle = str.substring(lAbs + 1, rAbs);
        String end = str.substring(rAbs + 1);
        return arithContainAbs(start + Math.abs(arithContainAbs(middle)) + end);        
    }

    /**
     * 不包含()和||的运算
     * @param str
     * @return
     * @throws Exception
     */
    public static double simpleArith(String str) throws Exception{
        return arithLevel1(str);
    }

    /**
     * +、-
     * @param str
     * @return
     * @throws Exception 
     */
    public static double arithLevel1(String str) throws Exception{
        String[][] sl = arithSplit(str, "\\+", "\\-");
        String[] ns = sl[0];
        String[] os = sl[1];
        double rs = arithLevel2(ns[0]);
        for(int i = 1; i < ns.length; i++){
            if      ("+".equals(os[i - 1])){
                rs += arithLevel2(ns[i]);
            }else if("-".equals(os[i - 1])){
                rs -= arithLevel2(ns[i]);
            }
        }
        return rs;
    }

    /**
     *  /、*、%
     * @param str
     * @return
     * @throws Exception 
     */
    public static double arithLevel2(String str) throws Exception {
        String[][] sl = arithSplit(str, "\\*", "/", "%");
        String[] ns = sl[0];
        String[] os = sl[1];
        double rs = arithLevel3(ns[0]);
        for(int i = 1; i < ns.length; i++){
            if      ("*".equals(os[i - 1])){
                rs *= arithLevel3(ns[i]);
            }else if("/".equals(os[i - 1])){
                rs /= arithLevel3(ns[i]);
            }else if("%".equals(os[i - 1])){
                rs %= arithLevel3(ns[i]);
            }
        }
        return rs;
    }

    /**
     * ^
     * @param str
     * @return
     * @throws Exception
     */
    public static double arithLevel3(String str) throws Exception{
        String[][] sl = arithSplit(str, "\\^");
        String[] ns = sl[0];
        String[] os = sl[1];
        double rs = arithLevel4(ns[0]);
        for(int i = 1; i < ns.length; i++){
            if("^".equals(os[i - 1])){
                rs = Math.pow(rs, arithLevel4(ns[i]));
            }
        }
        return rs;
    }

    /**
     * sin、cos、tan、cot、!、lg、ln
     * @param str
     * @return
     * @throws Exception 
     */
    public static double arithLevel4(String str) throws Exception{
        str = str.replaceAll("e", String.valueOf(Math.E)).replaceAll("π", String.valueOf(Math.PI));
        String doubleReg = "[-+]?([0-9]+(\\.[0-9]+)?|π|e)";
        double rs = 0;
        if      (str.matches("^\\|" + doubleReg + "\\|$")){//|-2.3|
            rs = Math.abs(Double.valueOf(str.substring(1, str.length() - 1)));
        }else if(str.matches("^" + doubleReg + "!$")){
            if(!str.matches("^[-+]?[0-9]+(\\.0+)?!$")){
                throw new Exception("int is needed : " + str);
            }
            int l = Integer.valueOf(str.replaceFirst("(\\.0+)?!", ""));
            rs = factorial(l);
        }else if(str.matches("^sin" + doubleReg + "°?$")){
            rs = Math.sin(getRadians(str.substring(3)));
        }else if(str.matches("^cos" + doubleReg + "°?$")){
            rs = Math.cos(getRadians(str.substring(3)));
        }else if(str.matches("^tan" + doubleReg + "°?$")){
            rs = Math.tan(getRadians(str.substring(3)));
        }else if(str.matches("^cot" + doubleReg + "°?$")){
            rs = 1d/Math.tan(getRadians(str.substring(3)));
        }else if(str.matches("^lg" + doubleReg + "$")){
            rs = Math.log10(Double.valueOf(str.substring(2)));
        }else if(str.matches("^ln" + doubleReg + "$")){
            rs = Math.log(Double.valueOf(str.substring(2)));
        }else{
            rs = Double.valueOf(str); 
        }
        return rs;
    }

    /**
     * 找到第一个'('对应的')'位置
     * @param str
     * @return
     * @throws Exception
     */
    public static int matchedRBracket(String str) throws Exception{
        int lBracket = str.indexOf('(');
        if(lBracket < 0){
            return lBracket;
        }
        Stack<Character> stack = new Stack<Character>();
        for(int i = lBracket; i < str.length(); i++){
            char ch = str.charAt(i);
            if      (ch == '('){
                stack.push(ch);
            }else if(ch == ')'){
                stack.pop();
            }
            if(stack.isEmpty()){
                return i;
            }
        }
        throw new Exception("parse error! \"(\" and \")\" not matches");
    }

    /**
     * 找到第一个'|'对应的'|'位置
     * @param str
     * @return
     * @throws Exception
     */
    public static int matchedRAbs(String str) throws Exception{
        if(!str.contains("|")){
            return -1;
        }
        Stack<String> stack = new Stack<String>();
        Pattern p = Pattern.compile("(?<=(^|[-+*/^])\\|{0,999999999})(\\|)|(\\|)(?=\\|{0,999999999}([-+*/^]|$))");
        Matcher m = p.matcher(str);
        while(m.find()){
            String group2 = m.group(2);
            String group3 = m.group(3);
            if      ("|".equals(group2) && group3 == null){
                stack.push(group2);
            } else {
                stack.pop();
            }
            if(stack.isEmpty()){
                return m.start();
            }
        }
        throw new Exception("parse error! \"|\" and \"|\" not matches");
    }

    /**
     * 解析表达式
     * @param str
     * @param opers
     * @return
     */
    public static String[][] arithSplit(String str, String... opers){
        String prefix = "(?<=([0-9]|π|e|°)[!|]?)";
        String suffix = "(?=(sin|cos|tan|cot|lg|ln|\\|)?[-+]?([0-9]|π|e|°))";
        String operStr = "(";
        for(int i = 0; i < opers.length; i++){
            operStr += (i == 0 ? "" : "|") + opers[i] + (i == opers.length - 1 ? ")" : "");
        }
        String regex = prefix + operStr + suffix;
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(str);
        int start = 0;
        int end   = 0;
        StringBuilder nsStr = new StringBuilder();
        StringBuilder osStr = new StringBuilder();
        while(m.find()){
            end = m.start();
            nsStr.append(str.substring(start, end)).append(",");
            osStr.append(m.group()).append(",");
            start = m.end();
        }
        nsStr.append(str.substring(start) + ",");
        String[] ns = nsStr.toString().split(",");
        String[] os = osStr.toString().split(",");
        String[][] rs = new String[2][];
        rs[0] = ns;
        rs[1] = os;
        return rs;
    }

    /**
     * 角度转弧度
     * @param str
     * @return
     */
    public static double getRadians(String str){
        if(str.endsWith("°")){
            return Math.toRadians(Double.valueOf(str.substring(0, str.length() - 1)));
        }
        return Double.valueOf(str);
    }

    /**
     * n!
     * @param l
     * @return
     */
    public static long factorial(int l){
        if(l == 1 || l == 0){
            return 1; 
        }else if(l > 1){
            return l * factorial(l - 1);
        }else{
            return -1 * factorial(Math.abs(l));
        }
    }

测试(误差未优化)

(|-0.6-|-0.4+0.1+0.1||+2)*5 :   14.0
3^|2-(1-1)|*(1-(1-2))!  :   18.0
sin(-π/2)+cos(45+3*(2+3))°  :   -0.4999999999999999
sin(-π/2)+cos(45+3*(2+3))°+3^|1-(1-1)|  :   2.5
  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值