`
enenxie
  • 浏览: 31762 次
社区版块
存档分类
最新评论

java实现四则运算

 
阅读更多

最近在考虑一个问题:公司项目可能会使用运算模板来计算相应的值,模板freemarker、velocity都是不错的选择。那通过模板将计算公式字符串组装出来后,就需要解析字符串得到计算结果,以下是我的实现:

public class Arithmetic {
    private char[] oper = { '+', '-', '*', '/', '(', ')' };

    public static void main(String args[]) {
        Arithmetic arith = new Arithmetic();
        System.out.println(System.currentTimeMillis());
        BigDecimal result = arith.parserExpression("(1+2/(3+(1+2.01)))*3/(1+2*(3+(1+2.01)))*3/(1+2*(3+(1+2.01)))*3/(1+2*(3+(1+2.01)))*3");
        System.out.println(System.currentTimeMillis());
        System.out.println(result.toString());
    }

    private boolean contains(char[] array, char v) {
        for (char e : array)
            if (e == v)
                return true;

        return false;
    }

    public BigDecimal parserExpression(String expression) {
        Stack<Object> stack1 = new Stack<Object>();

        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < expression.length(); i++) {
            char c = expression.charAt(i);
            if (this.contains(oper, c)) {
                if (sb.length() > 0) {
                    BigDecimal bigdecimal = new BigDecimal(sb.toString());
                    stack1.push(bigdecimal);
                    sb = new StringBuffer();
                }
                stack1.push(c);
            } else {
                sb.append(c);
                if (i == expression.length() - 1) {
                    BigDecimal bigdecimal = new BigDecimal(sb.toString());
                    stack1.push(bigdecimal);
                }

            }
        }

        Stack<Object> stack2 = new Stack<Object>();
        while (!stack1.isEmpty()) {
            Object o = stack1.pop();
            if (o instanceof Character) {
                char c = (Character) o;
                if (c == '(') {
                    //处理最小运算单元
                    BigDecimal subResult = this.subExpression(stack2);
                    stack2.push(subResult);
                    continue;
                }
            }
            stack2.push(o);
        }

        return this.subExpression(stack2);
    }

    private BigDecimal subExpression(Stack<Object> stack) {
        ArrayList<Object> list = new ArrayList<Object>();
        while (!stack.isEmpty()) {
            Object o = stack.pop();
            if (o instanceof Character) {
                char c = (Character) o;
                if (c == ')') {
                    break;
                }
            }
            list.add(o);
        }
        return calculation(list);
    }

    private BigDecimal calculation(ArrayList<Object> list) {
        Stack<Object> stack3 = new Stack<Object>();
        boolean priority = false;
        char sign = 0;
        for (int i = 0; i < list.size(); i++) {
            Object o = list.get(i);
            if (o instanceof Character) {
                char c = (Character) o;
                if (c == '*' || c == '/') {
                    priority = true;
                    sign = c;
                    continue;
                }
            }

            if (priority) {
                Object preObject = stack3.pop();
                BigDecimal preBigDecimal = (BigDecimal) preObject;
                BigDecimal nxtBigDecimal = (BigDecimal) o;
                if (sign == '*') {
                    BigDecimal result = preBigDecimal.multiply(nxtBigDecimal);
                    stack3.push(result);
                } else {
                    BigDecimal result = preBigDecimal.divide(nxtBigDecimal, 6, BigDecimal.ROUND_HALF_UP);
                    stack3.push(result);
                }
                priority = false;
                sign = 0;
                continue;
            }

            stack3.push(o);
        }

        BigDecimal result = new BigDecimal(0);

        while (!stack3.isEmpty()) {
            Object last = stack3.pop();
            if (last instanceof Character) {
                throw new RuntimeException();
            }

            if (stack3.isEmpty()) {
                result = result.add((BigDecimal) last);
                return result;
            }

            Object abs = stack3.pop();
            if (!(abs instanceof Character)) {
                throw new RuntimeException();
            }

            char c = (Character) abs;
            if (c == '+') {
                result = result.add((BigDecimal) last);
            } else {
                result = result.add(((BigDecimal) last).negate());
            }
        }
        return result;
    }
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics