java实现的计算器逻辑,可带括号

闲的没事写的一个计算器的核心逻辑
首先会判断算式的左括号 和 右括号是不是对等的。如果不对等则添加右括号
然后判断出来最小的括号,将里边的算式计算成数值,然后替换括号内的内容,
递归判断算式中是否有括号,如果没有了最后调用一下计算算式值的方法返回最终结果

package com.eleven.util;


import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Stack;

/**
 * @author eleven
 * @date 2021/11/2 13:35
 * @apiNote
 */
public class CalculateUtil {
    /** 数字栈 */
    private static final Stack<BigDecimal> numberStack = new Stack<>();
    /** 符号栈 */
    private static final Stack<Character> symbolStack = new Stack<>();
    /** 将百分号处理成小数 */
    private static final BigDecimal HUNDRED = new BigDecimal(100);
    /** 左括号 */
    private static final String LEFT_BRACKET = "(";
    /** 右括号 */
    private static final String RIGHT_BRACKET = ")";

    public static void main(String[] args) {
        String validate = "7+8*9/4";
        System.out.println(execute(validate));
    }

    /**
     * 运行方法
     * @param str   需要计算结果的式子
     * @return  String  返回运算的结果
     */
    public static String execute(String str){
        if(str.length() - str.replaceAll("[0-9]", "").length() == 0){
            throw new RuntimeException("算式错误");
        }
        String afterComputedStr =  str.contains(LEFT_BRACKET) ?
                getLeastParentheses(matchingParentheses(str)) :
                calculate(str);
        StringBuilder sb = new StringBuilder(afterComputedStr);
        StringBuilder reverseSb = new StringBuilder().append(Double.parseDouble(sb.reverse().toString()));
        return reverseSb.reverse().toString();
    }

    /**
     * 匹配括号的数量
     * @param str   要校验的字符串
     * @return  如果左括号和右括号的数量不一致的话添加右括号
     */
    private static String matchingParentheses(String str){
        str = str.replaceAll("()", "");
        int length = str.length();
        int left = length - str.replace("(","").length();
        int right = length - str.replace(")","").length();
        if(left != right){
            for (int i = 0; i < left - right; i++) {
                str += ")";
            }
        }
        return str;
    }

    private static String getLeastParentheses(String str){
        int lastIndex = str.lastIndexOf(LEFT_BRACKET);
        int latestIndex = str.indexOf(RIGHT_BRACKET,lastIndex);
        String subStr = str.substring(lastIndex + 1,latestIndex);
        String afterStr = str.substring(0, lastIndex) + calculate(subStr) + str.substring(latestIndex + 1);
        while(afterStr.contains(LEFT_BRACKET)){
            afterStr = getLeastParentheses(afterStr);
        }
        return calculate(afterStr);
    }

    private static String calculate(String str){
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < str.length(); i++) {
            char itemChar = str.charAt(i);
            if(isNumber(itemChar)){
                sb.append(itemChar);
            }
            if(isSymbol(itemChar)){
                boolean minusFlag = itemChar == '-' && (i == 0 || isSymbol(str.charAt(i - 1)));
                if(minusFlag){
                    sb.append("-");
                }else{
                    BigDecimal number = BigDecimal.valueOf(Double.parseDouble(sb.toString()));
                    sb = new StringBuilder();
                    if(itemChar == '%'){
                        number = number.divide(HUNDRED);
                        numberStack.push(number);
                    }else{
                        if(isLower(itemChar)){
                           numberStack.push(computed(symbolStack.pop(), number));
                           symbolStack.push(itemChar);
                        }else{
                            numberStack.push(number);
                            symbolStack.push(itemChar);
                        }
                    }
                }
            }
        }
        String lastStr = sb.toString();
        if(lastStr != null && lastStr.length() != 0){
            numberStack.push(BigDecimal.valueOf(Double.parseDouble(sb.toString())));
        }
        return computed() + "";

    }

    private static BigDecimal computed(){
        for (Iterator iterator = symbolStack.iterator();iterator.hasNext();){
            char symbol = symbolStack.pop();
            BigDecimal number = numberStack.pop();
            BigDecimal computed = computed(symbol, number);
            numberStack.push(computed);
        }
        return numberStack.pop();
    }

    /**
     * 计算
     * @param symbol    运算符
     * @param number    数字
     * @return
     */
    private static BigDecimal computed(char symbol,BigDecimal number){
        switch (symbol){
            case '*' :
                number = number.multiply(numberStack.pop()) ;
                break;
            case '/' :
                if(number.equals(BigDecimal.ZERO)){
                    throw new RuntimeException("不能除以0");
                }
                number = numberStack.pop().divide(number,BigDecimal.ROUND_UP);
                break;
            case '-' :
                number = numberStack.pop().subtract(number);
                break;
            case '+' :
                number = number.add(numberStack.pop());
                break;
            case '.' :
                number = number.divide(BigDecimal.TEN);
                break;
            default :
                break;
        }
        return number;
    }

    /**
     * 比较符号的优先级
     * @param symbol    算式中的运算符
     * @return
     */
    private static boolean isLower(char symbol){
        if(symbolStack.isEmpty()){
            return false;
        }
        Map<Character, Integer> priorityMap = getPriorityMap();
        return priorityMap.get(symbol) >= priorityMap.get(symbolStack.peek());
    }

    private static boolean noSymbol(String str){
        return str.length() - str.replaceAll("[-+/*.%(^)]","").length() == 0;
    }

    private static Map<Character,Integer> getPriorityMap(){
        Map<Character,Integer> map = new HashMap<>(5);
        map.put('%', 0);
        map.put('/', 1);
        map.put('*', 1);
        map.put('-', 2);
        map.put('+', 2);
        return map;
    }

    /**
     * 是否是数字
     * @param itemChar  字符
     * @return
     */
    public static boolean isNumber(char itemChar){
        return itemChar == '.' || itemChar >= '0' && itemChar <= '9';
    }

    /**
     * 是否是符号
     * @param itemChar  符号
     * @return
     */
    public static boolean isSymbol(char itemChar){
        return !isNumber(itemChar);
    }
}

  • 7
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值