JAVA实现算术表达式的求值

补充中间有补充代码提示的地方就好能附上说明更好

package eval;

public class Util {

    /**
     * 计算表达式 express 的值
     * 如: eval("3+5*3") 返回 18
     */
    public static double eval(String express) {
        char[] chars = express.toCharArray();

        // .... 补充代码 ....

        return 0;
    }

    /**
     * 求 a 和 b 进行算术运算的结果。 
     * 例如:calculate(3, 5, '+') 返回  8
     */
    private static double calculate(double a, double b, char op) {
        switch (op) {
        case '+':
            return a + b; 
        case '-':
            return a - b; 
        case '*':
            return a * b; 
        case '/':
            return a / b; 
        default:
            throw new RuntimeException("不支持此运算"); 
        }
    }
}

4个回答

import java.util.Collections;
import java.util.Stack;

public class Calculator {
    private Stack<String> postfixStack  = new Stack<String>();//后缀式栈
    private Stack<Character> opStack  = new Stack<Character>();//运算符栈
    private int [] operatPriority  = new int[] {0,3,2,1,-1,1,0,2};//运用运算符ASCII码-40做索引的运算符优先级
    public static void main(String[] args) {
        System.out.println(5+12*(3+5)/7.0);
        Calculator cal  = new Calculator();
        String s = "5+12*(3+5)/7";
        double result  = cal.calculate(s);
        System.out.println(result);
    }

    /**
     * 按照给定的表达式计算
     * @param expression 要计算的表达式例如:5+12*(3+5)/7
     * @return
     */
    public double calculate(String expression) {
        Stack<String> resultStack  = new Stack<String>();
        prepare(expression);
        Collections.reverse(postfixStack);//将后缀式栈反转
        String firstValue  ,secondValue,currentValue;//参与计算的第一个值,第二个值和算术运算符
        while(!postfixStack.isEmpty()) {
            currentValue  = postfixStack.pop();
            if(!isOperator(currentValue.charAt(0))) {//如果不是运算符则存入操作数栈中
                resultStack.push(currentValue);
            } else {//如果是运算符则从操作数栈中取两个值和该数值一起参与运算
                 secondValue  = resultStack.pop();
                 firstValue  = resultStack.pop();
                 String tempResult  = calculate(firstValue, secondValue, currentValue.charAt(0));
                 resultStack.push(tempResult);
            }
        }
        return Double.valueOf(resultStack.pop());
    }

    /**
     * 数据准备阶段将表达式转换成为后缀式栈
     * @param expression
     */
    private void prepare(String expression) {
        opStack.push(',');//运算符放入栈底元素逗号,此符号优先级最低
        char[] arr  = expression.toCharArray();
        int currentIndex  = 0;//当前字符的位置
        int count = 0;//上次算术运算符到本次算术运算符的字符的长度便于或者之间的数值
        char currentOp  ,peekOp;//当前操作符和栈顶操作符
        for(int i=0;i<arr.length;i++) {
            currentOp = arr[i];
            if(isOperator(currentOp)) {//如果当前字符是运算符
                if(count > 0) {
                    postfixStack.push(new String(arr,currentIndex,count));//取两个运算符之间的数字
                }
                peekOp = opStack.peek();
                if(currentOp == ')') {//遇到反括号则将运算符栈中的元素移除到后缀式栈中直到遇到左括号
                    while(opStack.peek() != '(') {
                        postfixStack.push(String.valueOf(opStack.pop()));
                    }
                    opStack.pop();
                } else {
                    while(currentOp != '(' && peekOp != ',' && compare(currentOp,peekOp) ) {
                        postfixStack.push(String.valueOf(opStack.pop()));
                        peekOp = opStack.peek();
                    }
                    opStack.push(currentOp);
                }
                count = 0;
                currentIndex = i+1;
            } else {
                count++;
            }
        }
        if(count > 1 || (count == 1 && !isOperator(arr[currentIndex]))) {//最后一个字符不是括号或者其他运算符的则加入后缀式栈中
            postfixStack.push(new String(arr,currentIndex,count));
        } 

        while(opStack.peek() != ',') {
            postfixStack.push(String.valueOf( opStack.pop()));//将操作符栈中的剩余的元素添加到后缀式栈中
        }
    }

    /**
     * 判断是否为算术符号
     * @param c
     * @return
     */
    private boolean isOperator(char c) {
        return c == '+' || c == '-' || c == '*' || c == '/' || c == '(' ||c == ')';
    }

    /**
     * 利用ASCII码-40做下标去算术符号优先级
     * @param cur
     * @param peek
     * @return
     */
    public  boolean compare(char cur,char peek) {// 如果是peek优先级高于cur,返回true,默认都是peek优先级要低
        boolean result  = false;
        if(operatPriority[(peek)-40] >= operatPriority[(cur) - 40]) {
           result = true;
        }
        return result;
    }

    /**
     * 按照给定的算术运算符做计算
     * @param firstValue
     * @param secondValue
     * @param currentOp
     * @return
     */
    private String calculate(String firstValue,String secondValue,char currentOp) {
        String result  = "";
        switch(currentOp) {
            case '+':
                result = String.valueOf(ArithHelper.add(firstValue, secondValue));
                break;
            case '-':
                result = String.valueOf(ArithHelper.sub(firstValue, secondValue));
                break;
            case '*':
                result = String.valueOf(ArithHelper.mul(firstValue, secondValue));
                break;
            case '/':
                result = String.valueOf(ArithHelper.div(firstValue, secondValue));
                break;
        }
        return result;
    }
}
public class Util {
    public static void main(String[] args) {
        String expression = "(2*(1+3)+8)/4+1";
        Stack<Character> characterStack = new Stack<>();
        Stack<Double> integerStack = new Stack<>();
        // 1.拆分字符串
        char[] arr = expression.toCharArray();
        // 2.将拆分好的字符依次放入两个栈中
        Double result = setStackDate(arr, characterStack, integerStack);

        System.out.println(expression + "=" + result);
    }

    /**
     * 将拆分好的字符依次放入两个栈中
     *
     * @param arr            需要运算的字符
     * @param characterStack 符号运算符
     * @param integerStack   数字运算符
     */
    private static Double setStackDate(char[] arr, Stack<Character> characterStack, Stack<Double> integerStack) {

        for (int i = 0; i < arr.length; i++) {
            if (arr[i] == '(') {
                characterStack.push(arr[i]);
                continue;
            }
            if (arr[i] == ')') {
                // 3.根据规则,弹栈并运算
                calculate(characterStack, integerStack);
                continue;
            }
            // 如果是数字
            if ('0' <= arr[i] && arr[i] <= '9') {
                integerStack.push(Double.valueOf(String.valueOf(arr[i])));
            } else {
                // 如果是运算符
                characterStack.push(arr[i]);
            }
        }
        // 将栈中,最后的结果算出
        Double num1 = integerStack.pop();
        Double num2 = integerStack.pop();
        integerStack.push(num2);
        integerStack.push(num1);
        return calculate(characterStack, integerStack);
    }

    /**
     * 根据规则进行计算
     *
     * 规则:
     * integerStack弹出两位,与characterStack弹出的一位运算符进行计算,并把结果压回到integerStack,直到characterStack为空
     *
     * @param characterStack 字符栈
     * @param integerStack   数字栈
     */
    private static Double calculate(Stack<Character> characterStack, Stack<Double> integerStack) {
        Double sum = 0.0;
        while (!characterStack.empty()) {
            Double num1 = integerStack.pop();
            Double num2 = integerStack.pop();
            Character operator = characterStack.pop();
            // 乘/除 检验
            if (!characterStack.empty() && (characterStack.peek() == '*' || characterStack.peek() == '/')) {
                Character speOperator = characterStack.pop();
                Double speNum = integerStack.pop();
                if (speOperator == '*') {
                    num2 = speNum * num2;
                } else if (speOperator == '/') {
                    num2 = speNum / num2;
                }
            }
            if (operator == '+') {
                sum = num2 + num1;
            } else if (operator == '-') {
                sum = num2 - num1;
            } else if (operator == '*') {
                sum = num2 * num1;
            } else if (operator == '/') {
                sum = num2 / num1;
            }
            integerStack.push(sum);
            // '(' 检验
            if (!characterStack.empty() && characterStack.peek() == '(') {
                characterStack.pop();
                return sum;
            }
        }
        return sum;
    }
}

Scanner sc=new Scanner(System.in);
char[] chars = express.toCharArray();
System.out.println("请输入一个数字");
double a=sc.nextDouble();

    System.out.println("请输入一个数");
    double b=sc.nextDouble();
    System.out.println("请在输入数字");
    double c=sc.nextDouble();
    double d=a+(b*c); 
    System.out.println(d);
    return d;
}
public static void main(String[] args) {
    HJ c=new HJ();
    double g=c.eval("d");

}

不知道这是不是你想要的结果

public static double eval(String express) throws ScriptException {
        char[] chars = express.toCharArray();
        // .... 补充代码 ....

        ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
        Object re = null;
        try {
            re = engine.eval(express);
        } catch (ScriptException e) {
            //e.printStackTrace();
            System.out.println("含有非法字符");
            return 0d;
        }
        if(re instanceof Double){
            return (double)re;
        }else{
            return Double.valueOf((int)re);
        }
    }
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问