最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

問題

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

如何解決

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

代碼

操作符枚舉類

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;
        }
    }
}

表達式工具類

public class ExprUtils {

    /*判斷中綴表達式是否合法*/
    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++) {
            //先判斷 '-' 是不是負數(shù)符號
            if('-' == str.charAt(i)) {
                if( 0 == i || Operator.notRightBracket(str.charAt(i - 1))) //如果 - 在第一位或者前面有+-*/(,一定是作為負數(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;
    }

    /**
     * 將中綴表達式轉(zhuǎn)化為后綴表達式
     *
     * @param exp 中綴表達式
     * @return 后綴表達式
     */
    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)) ) {
                // 如果是正號就不用加入,負號或者數(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;
    }

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

        }

        return stack.pop();
    }
}

測試類

class ExprUtilsTest {

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

總結(jié)

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

相關(guān)文章

  • Java中的ByteArrayInputStream詳解

    Java中的ByteArrayInputStream詳解

    Java中,ByteArrayInputStream類是實現(xiàn)內(nèi)存級別的字節(jié)流讀取的工具,可以從字節(jié)數(shù)組中讀取數(shù)據(jù),這個類位于java.io包中,繼承自InputStream,ByteArrayInputStream的主要特點有:在內(nèi)存中操作,不涉及磁盤IO,可以重用流讀取數(shù)據(jù)
    2024-09-09
  • 永久解決 Intellij idea 報錯:Error :java 不支持發(fā)行版本5的問題

    永久解決 Intellij idea 報錯:Error :java 不支持發(fā)行版本5的問題

    這篇文章主要介紹了永久解決 Intellij idea 報錯:Error :java 不支持發(fā)行版本5的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • 本真的REST架構(gòu)風格理解

    本真的REST架構(gòu)風格理解

    這篇文章主要為大家介紹了本真的REST架構(gòu)風格的深入理解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-03-03
  • Java 歸并排序算法、堆排序算法實例詳解

    Java 歸并排序算法、堆排序算法實例詳解

    這篇文章主要介紹了Java 歸并排序算法、堆排序算法實例詳解,需要的朋友可以參考下
    2017-05-05
  • 通過FeignClient調(diào)用微服務(wù)提供的分頁對象IPage報錯的解決

    通過FeignClient調(diào)用微服務(wù)提供的分頁對象IPage報錯的解決

    這篇文章主要介紹了通過FeignClient調(diào)用微服務(wù)提供的分頁對象IPage報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • java編程下字符串的16位,32位md5加密實現(xiàn)方法

    java編程下字符串的16位,32位md5加密實現(xiàn)方法

    下面小編就為大家?guī)硪黄猨ava編程下字符串的16位,32位md5加密實現(xiàn)方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-09-09
  • maven異常Invalid?bound?statement(not?found)的問題解決

    maven異常Invalid?bound?statement(not?found)的問題解決

    本文詳細介紹了Maven項目中常見的Invalidboundstatement異常及其解決方案,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-12-12
  • Mybatis批量修改的操作代碼

    Mybatis批量修改的操作代碼

    這篇文章主要介紹了Mybatis批量修改的操作代碼,包括整體批量修改的詳細代碼,代碼簡單易懂,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2017-09-09
  • IntelliJ IDEA 警告“Immutable object is modified”的問題排查與解決方法

    IntelliJ IDEA 警告“Immutable object is&nbs

    IntelliJ IDEA 作為業(yè)界領(lǐng)先的集成開發(fā)環(huán)境,憑借其強大的靜態(tài)代碼分析引擎,能夠在編譯階段就敏銳地捕捉到此類潛在風險,并彈出 Immutable object is modified警告,下面我們就來看看如何解決吧
    2026-03-03
  • Java集合中的LinkedHashSet源碼解讀

    Java集合中的LinkedHashSet源碼解讀

    這篇文章主要介紹了Java集合中的LinkedHashSet源碼解讀,在LinkedHashMap中,雙向鏈表的遍歷順序通過構(gòu)造方法指定,如果沒有指定,則使用默認順序為插入順序,即accessOrder=false,需要的朋友可以參考下
    2023-12-12

最新評論

海兴县| 北碚区| 杭锦后旗| 常宁市| 侯马市| 鄂托克旗| 汪清县| 晋宁县| 龙陵县| 荥阳市| 上犹县| 岚皋县| 盐城市| 安西县| 滦平县| 大荔县| 阿拉尔市| 牟定县| 灌南县| 自贡市| 刚察县| 苍山县| 玛沁县| 枣强县| 高邮市| 新余市| 且末县| 微博| 安庆市| 枣阳市| 利辛县| 南丰县| 鄂尔多斯市| 陵川县| 原平市| 南投市| 电白县| 宁德市| 深水埗区| 肃南| 长汀县|