亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Java如何使用逆波蘭式(后綴表達(dá)式)計(jì)算表達(dá)式的值

 更新時間:2024年06月17日 10:30:11   作者:編程經(jīng)驗(yàn)分享  
這篇文章主要介紹了Java如何使用逆波蘭式(后綴表達(dá)式)計(jì)算表達(dá)式的值,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教

問題

實(shí)際項(xiàng)目中需要對接口的返回結(jié)果做處理,按照配置中的返回結(jié)果字段和算術(shù)運(yùn)算符(+ - * /)和左右括號組合得到一個算術(shù)表達(dá)式,并計(jì)算得到值返回。

如何解決

  • 獲取到接口的返回值后,便可以得到一個具體的中綴表達(dá)式
  • 將中綴表達(dá)式轉(zhuǎn)化成后綴表達(dá)式(逆波蘭式)
  • 計(jì)算后綴表達(dá)式的值

代碼

操作符枚舉類

public enum Operator {

    ADD(30, '+'),
    SUB(30, '-'),
    MUL(40, '*'),
    DIV(40, '/'),
    LEFT(0, '('),
    RIGHT(0, ')');

    static {
        map = Arrays.stream(values()).collect(toMap(ExprUtils.Operator::getSymbol, e -> e));
    }

    private final int priority;
    private final char symbol;

    private static final Map<Character, ExprUtils.Operator> map;

    Operator(Integer priority, Character symbol) {
        this.priority = priority;
        this.symbol = symbol;
    }

    public Character getSymbol() {
        return this.symbol;
    }

    //返回對應(yīng)的優(yōu)先級數(shù)字
    public static int getPriority(Character symbol) {
        ExprUtils.Operator operator = map.get(symbol);
        assert Objects.nonNull(operator);
        return operator.priority;
    }

    public static boolean notRightBracket(Character symbol) {
        ExprUtils.Operator operator = map.get(symbol);
        if (Objects.isNull(operator)) {
            return false;
        }
        return !operator.equals(RIGHT);
    }

    public static boolean isOperator(Character symbol) {
        ExprUtils.Operator operator = map.get(symbol);
        if (Objects.isNull(operator)) {
            return false;
        }
        switch (operator) {
            case ADD:
            case SUB:
            case MUL:
            case DIV: return true;
            default: return false;
        }
    }
}

表達(dá)式工具類

public class ExprUtils {

    /*判斷中綴表達(dá)式是否合法*/
    public static boolean expressionCheck(String str) {
        Deque<Character> stack = new LinkedList<>();
        //不合法情況1:括號不匹配
        for(char ch : str.toCharArray()) {
            if(ch == '(') {
                stack.push(ch);
            }

            if(ch == ')') {
                if(stack.isEmpty()) {
                    return false;
                }
                stack.pop();
            }
        }
        if (!stack.isEmpty()) {
            return false;
        }

        //不合法情況2:操作符左右元素不合法
        for(int i = 0 ; i < str.length() ; i++) {
            //先判斷 '-' 是不是負(fù)數(shù)符號
            if('-' == str.charAt(i)) {
                if( 0 == i || Operator.notRightBracket(str.charAt(i - 1))) //如果 - 在第一位或者前面有+-*/(,一定是作為負(fù)數(shù)符號而非操作符
                    i++;
            }
            if(Operator.isOperator(str.charAt(i))) {
                if( 0 == i || str.length() - 1 == i)
                    return false;
                if( Operator.isOperator(str.charAt(i - 1)) || Operator.isOperator(str.charAt(i + 1)) )
                    return false;
                if( '(' == str.charAt(i - 1) || ')' == str.charAt(i + 1) )
                    return false;
            }
        }

        //不合法情況3:左括號和右括號相鄰,例:a+()和(a+b)(a+b)
        for(int i = 0 ; i < str.length() ; i++) {
            if(str.charAt(i) =='(' && i + 1 < str.length() && str.charAt(i + 1) == ')')
                return false;
            if(str.charAt(i) == ')' && i + 1 < str.length() && str.charAt(i + 1) == '(')
                return false;
        }
        return true;
    }

    /**
     * 將中綴表達(dá)式轉(zhuǎn)化為后綴表達(dá)式
     *
     * @param exp 中綴表達(dá)式
     * @return 后綴表達(dá)式
     */
    public static List<String> parseExpression(String exp) {

        Deque<Character> operation = new LinkedList<>();
        List<String> target = new ArrayList<>();

        for (int i = 0; i < exp.length(); i++) {
            if(((exp.charAt(i) == '-' || exp.charAt(i) == '+') && (i == 0 || Operator.notRightBracket(exp.charAt(i - 1))))
                    || Character.isDigit(exp.charAt(i)) ) {
                // 如果是正號就不用加入,負(fù)號或者數(shù)字本身都要加入
                StringBuilder tempStr = new StringBuilder(exp.charAt(i) != '+' ? exp.substring(i, i + 1) : "");
                while (i + 1 <  exp.length() && Character.isDigit(exp.charAt(i + 1))) {
                    tempStr.append(exp.charAt(++i));
                }
                target.add(tempStr.toString());
            } else {
                if ('(' == exp.charAt(i)) {
                    operation.push(exp.charAt(i));
                } else if (')' == exp.charAt(i)) {
                    while ('(' != operation.peek()) {
                        target.add(operation.pop().toString());
                    }
                    operation.pop();
                } else {
                    while (!operation.isEmpty()
                            && Operator.getPriority(operation.peek()) >= Operator.getPriority(exp.charAt(i))) {
                        target.add(operation.pop().toString());
                    }

                    operation.push(exp.charAt(i));
                }
            }
        }

        while (!operation.isEmpty()) {
            target.add(operation.pop().toString());
        }

        return target;
    }

    /**
     * 計(jì)算后綴表達(dá)式
     *
     * @param list 后綴表達(dá)式
     * @return 計(jì)算結(jié)果
     */
    public static int calculate(List<String> list) {
        Stack<Integer> stack = new Stack<>();// 創(chuàng)建棧
        for (String item : list) {
            if (item.matches("^-?\\d+(\\.\\d+)?$")) { //使用正則表達(dá)式匹配多位數(shù)
                stack.push(Integer.parseInt(item));
            } else {
                int num2 = stack.pop();	// pop出兩個數(shù),并運(yùn)算, 再入棧
                int num1 = stack.pop();
                int res;
                switch (item) {
                    case "+": res = num1 + num2; break;
                    case "-": res = num1 - num2; break;
                    case "*": res = num1 * num2; break;
                    case "/": res = num1 / num2; break;
                    default: throw new RuntimeException("運(yùn)算符有誤");
                }
                stack.push(res);
            }

        }

        return stack.pop();
    }
}

測試類

class ExprUtilsTest {

    @Test
    void calculate() {
        String infixExpression = "-6+((-2)+(2+4))";
        if (!ExprUtils.expressionCheck(infixExpression)) {
            System.out.println("表達(dá)式不合法");
        } else {
            System.out.println("中綴表達(dá)式為:" + infixExpression);
            List<String> calculateExpression = ExprUtils.parseExpression(infixExpression);
            System.out.println("后綴表達(dá)式為:" + calculateExpression);
            System.out.printf("Answer=%d", ExprUtils.calculate(calculateExpression));
        }
    }
}

總結(jié)

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 基于@GetMapping注解攜帶參數(shù)的方式

    基于@GetMapping注解攜帶參數(shù)的方式

    這篇文章主要介紹了基于@GetMapping注解攜帶參數(shù)的方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • java求余的技巧匯總

    java求余的技巧匯總

    這篇文章主要給大家介紹了關(guān)于java求余技巧的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 徹底搞懂Java多線程(三)

    徹底搞懂Java多線程(三)

    這篇文章主要給大家介紹了關(guān)于Java面試題之多線程和高并發(fā)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-07-07
  • Java泛型定義與用法入門示例

    Java泛型定義與用法入門示例

    這篇文章主要介紹了Java泛型定義與用法,結(jié)合實(shí)例形式分析了java泛型的功能、定義、應(yīng)用場景及相關(guān)使用注意事項(xiàng),需要的朋友可以參考下
    2019-08-08
  • 在Eclipse中運(yùn)行Solr 基礎(chǔ)知識

    在Eclipse中運(yùn)行Solr 基礎(chǔ)知識

    Solr我還是個菜鳥,寫這一些文章只是記錄一下最近一段時間學(xué)習(xí)Solr的心得,望各位同仁不要見笑,還希望多多指點(diǎn)
    2012-11-11
  • SpringBoot實(shí)現(xiàn)優(yōu)雅停機(jī)的三種方式

    SpringBoot實(shí)現(xiàn)優(yōu)雅停機(jī)的三種方式

    優(yōu)雅停機(jī)(Graceful?Shutdown)是指應(yīng)用在接收到停止信號后,能夠妥善處理現(xiàn)有請求、釋放資源,然后再退出的過程,本文將詳細(xì)介紹SpringBoot中實(shí)現(xiàn)優(yōu)雅停機(jī)的三種方式,需要的朋友可以參考下
    2025-04-04
  • maven打包如何指定jdk的版本

    maven打包如何指定jdk的版本

    這篇文章主要介紹了maven打包如何指定jdk的版本問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Spring Boot使用和配置Druid

    Spring Boot使用和配置Druid

    本篇文章主要介紹了Spring Boot使用和配置Druid,Druid號稱是Java語言中最好的數(shù)據(jù)庫連接池,并且能夠提供強(qiáng)大的監(jiān)控和擴(kuò)展功能
    2017-04-04
  • java發(fā)送HttpClient請求及接收請求結(jié)果過程的簡單實(shí)例

    java發(fā)送HttpClient請求及接收請求結(jié)果過程的簡單實(shí)例

    下面小編就為大家?guī)硪黄猨ava發(fā)送HttpClient請求及接收請求結(jié)果過程的簡單實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    MyBatis?多表聯(lián)合查詢及優(yōu)化方法

    大家都知道Hibernate 是全自動的數(shù)據(jù)庫持久層框架,它可以通過實(shí)體來映射數(shù)據(jù)庫,通過設(shè)置一對多、多對一、一對一、多對多的關(guān)聯(lián)來實(shí)現(xiàn)聯(lián)合查詢,接下來通過本文給大家介紹MyBatis?多表聯(lián)合查詢及優(yōu)化,需要的朋友可以參考下
    2022-08-08

最新評論