表达式求值

package com.company;

import java.util.Stack;

public class Main {

    public static void main(String[] args) {
   // write your code here
        String string = "(0!+1)*2^(3!+4)-(5!-67-(10+12))";
        Evaluate evaluate = new Evaluate(string);
        System.out.println(evaluate.result());
        System.out.println("RPN:"+evaluate.getRPN());
    }
}

class Evaluate{
    private String string;
    private String RPN; //后缀表达式
    private int n=0;

    public Evaluate(String string){
        RPN = "";
        this.string = new String(string+'\0');

    }
    
    private float evaluate(){
        Stack<Character> operatorStack = new Stack<Character>();//操作符栈
        Stack<Float> numberStack = new Stack<Float>();          //操作数栈

        operatorStack.push('\0');                         //尾哨兵首先推入操作符栈中
        int i=0;

        while (!operatorStack.empty()){
            if (Character.isDigit(string.charAt(i))){   //如果是数字读取数字
                i = Util.readNumber(string,numberStack,i);
                RPN+=(numberStack.peek()+" ");
            }else {
                switch (Util.orderBetween(operatorStack.peek(),string.charAt(i))){ //比较操作符的优先级
                    case '<' : {                                                   //优先级小于前一运算符则推入操作数栈中
                        char operator  = string.charAt(i);
                        check1(operator,numberStack.size());                       //检查是否符合中綴表达式的语法
                        operatorStack.push(operator);
                        i++;
                    }          break;
                    case '=' : {
                        operatorStack.pop(); //优先级相等则推出操作符栈
                        i++;
                    }
                               break;
                    case '>' : {            //栈顶符号的优先级更高时 出栈执行运算
                        char op = operatorStack.pop(); RPN += (op+" ");
                        check2(op);
                        if (op == '!') //一元运算符
                            numberStack.push(Util.calculate(numberStack.pop())); //将结果推入操作数栈中
                        else {         //二元运算符
                            float number1 = numberStack.pop(); float number2 = numberStack.pop();
                            numberStack.push(Util.calculate(number2,op,number1));//将结果推入操作数栈中
                             }
                    }          break;
                    default: System.out.println("请检查括号是否匹配以及表达式的正确性"); //语法错误
                             System.exit(-1);
                }
            }
        }
        return numberStack.peek();//返回结果
    }
    
    private void check1(char ch,int size){
        switch (ch){
            case '+' :
            case '-' :
            case '*' :
            case '/' :
            case '!' :
            case '^' : {
                if ((size-n) != 1) {  //每个操作即将符入栈时,应该操作数栈的规模比操作符栈中规模大一
                    System.out.println("不符合中綴表达式的语法");
                    System.exit(-1);
                }
                n++;//符号入栈时 操作符的规模加一
            }     break;
        }
    }
    private void check2(char operator){
        switch (operator){
            case '+' :
            case '-' :
            case '*' :
            case '/' :
            case '!' :
            case '^' : n--; break; //相应的操作符出栈时,操作符的规模减一
        }
    }
    public float result(){ return evaluate(); }
    public String getRPN(){ return RPN; }
}

class Util {
    public static char[][] priorityLevel = {  //栈顶运算符和当前的运算的优先级
            /* |-------------- 当前运算符 --------------| */
            /*       +    -    *     /    ^    !    (    )   \0*/
    /* |   +  */   {'>', '>', '<', '<', '<', '<', '<', '>', '>'},

    /* |   -  */   {'>', '>', '<', '<', '<', '<', '<', '>', '>'},

    /* |   *  */   {'>', '>', '>', '>', '<', '<', '<', '>', '>'},

    /*   /  */   {'>', '>', '>', '>', '<', '<', '<', '>', '>'},

    /*   ^  */   {'>', '>', '>', '>', '<', '<', '<', '>', '>'},

    /*   !  */   {'>', '>', '>', '>', '>', '>', ' ', '>', '>'},

    /*   (  */   {'<', '<', '<', '<', '<', '<', '<', '=', ' '},

    /* |   )  */   {' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '},

    /* | \0  */    {'<', '<', '<', '<', '<', '<', '<', ' ', '='}
        };

    public static char orderBetween(char ch1,char ch2){
        return priorityLevel[getIndex(ch1)][getIndex(ch2)];
    }

    public static int getIndex(char ch){ //取得运算符优先级的下标
        switch (ch){
            case '+' : return 0;
            case '-' : return 1;
            case '*' : return 2;
            case '/' : return 3;
            case '^' : return 4;
            case '!' : return 5;
            case '(' : return 6;
            case ')' : return 7;
            case '\0': return 8;
            default: { System.out.println("operator error1"); }
        }
        System.exit(-1);  return -1;
    }

    public static float calculate(float number1, char operator, float number2) {
        switch (operator){
            case '+' : return number1+number2;
            case '-' : return number1-number2;
            case '*' : return number1*number2;
            case '/' : try{
                       return number1/number2; }
                            catch (Exception ex){System.out.println("被除数不能为零");}
            case '^' : {
                       float temp = number1;
                       for (int i=1; i<number2; i++) temp *= number1;
                       return temp;
            }
            default: System.out.println("operator error2");
        }
        System.exit(-1); return -1;
    }

    public static float calculate(float number){  //阶乘
        float result = 1;
        for (int i=1; i<=number; i++)  result *= i;
        return result;
    }

    public static int readNumber(String string,Stack<Float> numberStack,int i){

        String number="";
        while(Character.isDigit(string.charAt(i)))      //读取数字
            number += string.charAt(i++);

        numberStack.push(Float.parseFloat(number));

        if (string.charAt(i) != '.') return i;         //如果没有小数位
        float a=1;                                     //如果有小数位
        while(Character.isDigit(string.charAt(++i))){
            numberStack.push(numberStack.pop() +
                    (Float.parseFloat(string.substring(i,i+1))*(a/=10)));
        }
        return i;
    }
}

借鉴《《数据结构(c++语言版)》》

运行结果:2017

RPN:0.0 ! 1.0 + 2.0 3.0 ! 4.0 + ^ * 5.0 ! 67.0 - 10.0 12.0 + - -

转载于:https://my.oschina.net/u/3737002/blog/1594299

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值