黑马程序员技术交流社区

标题: 算数表达式求解代码 [打印本页]

作者: cat73    时间: 2016-8-19 05:54
标题: 算数表达式求解代码
本帖最后由 cat73 于 2016-8-19 19:47 编辑

正在外面旅游,拿平板的破虚拟键盘 + 记事本写的,所以稍微乱了点,回家再改,见谅 0.0
目前也比较简单,不支持数字前的正负号神马的。。。
输出示例:
[Java] 纯文本查看 复制代码
13 + 2 * (5 - 1) = 21.0
(12345 + 54321) * 10 = 666660.0
1 * (2 + 3) - 4 / (5 + 6) = 4.636363636363637
8.8 / ((5. - 3) * 2) * .1 = 0.22000000000000003
Exception in thread "main" java.lang.IllegalArgumentException: TODO index: 6
8888.8.8 + 1112
      ^
        at org.cat73.eval.Eval.eval(Eval.java:22)
        at org.cat73.eval.Eval.test(Eval.java:127)
        at org.cat73.eval.Eval.main(Eval.java:135)

代码:
[Java] 纯文本查看 复制代码
package org.cat73.eval;
import java.util.Stack;

public class Eval {
    public static double eval(String expression) {
        Stack<Character> operatorStack = new Stack<>();
        Stack<Double> numStack = new Stack<>();
        StringBuilder numString = new StringBuilder();
        boolean flag = false;

        for(int i = 0; i < expression.length(); i++) {
            char ch = expression.charAt(i);

            if (ch == ' ') {
                    continue;
            } else if (ch >= '0' && ch <= '9') {
                numString.append(ch);
                continue;
            } else if (ch == '.') {
                if(flag) {
                    throw new IllegalArgumentException(getThrowMsg(expression, i, "TODO index: %d", i));
                } else {
                    numString.append(ch);
                    flag = true;
                }
                continue;
            }

            if(numString.length() > 0) {
                    numStack.push(Double.valueOf(numString.toString()));
                    numString = new StringBuilder();
                flag = false;
            }

            switch(ch) {
                case '(':
                    operatorStack.push(ch);
                    break;
                case '*':
                case '/':
                case '+':
                case '-':
                    loop:
                    while(!operatorStack.empty()) {
                        switch(operatorStack.peek()) {
                            case '(':
                                break loop;
                            case '*':
                            case '/':
                            case '+':
                            case '-':
                                if(getPriority(operatorStack.peek()) >= getPriority(ch)) {
                                    numStack.push(calc(numStack.pop(), numStack.pop(), operatorStack.pop()));
                                } else {
                                    break loop;
                                }
                                break;
                        }
                    }
                    operatorStack.push(ch);
                    break;
                case ')':
                    while(!operatorStack.empty()) {
                        char operator = operatorStack.pop();
                        if(operator == '(') {
                            break;
                        } else {
                            numStack.push(calc(numStack.pop(), numStack.pop(), operator));
                        }
                    }
                    break;
                default:
                    throw new IllegalArgumentException(getThrowMsg(expression, i, "Unknow operator: %c, index: %d", ch, i));
            }
        }

        if(numString.length() > 0) {
                numStack.push(Double.valueOf(numString.toString()));
        }

        while(!operatorStack.empty()) {
                char operator = operatorStack.pop();
                if(operator == '(') {
                        continue;
                }

            numStack.push(calc(numStack.pop(), numStack.pop(), operator));
        }

        return numStack.pop();
    }

    private static int getPriority(char operator) {
        switch(operator) {
            case '*':
            case '/':
                return 2;
            case '+':
            case '-':
                return 1;
            default:
                throw new IllegalArgumentException("Unknow operator: " + operator);
        }
    }

    private static double calc(double n2, double n1, char operator) {
        switch(operator) {
            case '+':
                return n1 + n2;
            case '-':
                return n1 - n2;
            case '*':
                return n1 * n2;
            case '/':
                return n1 / n2;
            default:
                throw new IllegalArgumentException("Unknow operator: " + operator);
        }
    }

    private static String getThrowMsg(String expression, int index, String msg, Object... objs) {
        return String.format("%s\n%s\n%s", String.format(msg, objs), expression, String.format("%" + (index + 1) + "c", '^'));
    }

    private static void test(String expression) {
        System.out.println(expression + " = " + eval(expression));
    }

    public static void main(String[] args) {
        test("13 + 2 * (5 - 1)");
        test("(12345 + 54321) * 10");
        test("1 * (2 + 3) - 4 / (5 + 6)");
        test("8.8 / ((5. - 3) * 2) * .1");
        test("8888.8.8 + 1112");
    }
}









欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2