您的位置:首页 > 编程语言 > Java开发

java四则混合运算工具类备忘

2016-01-28 20:14 381 查看
package com.api.test;

import java.util.Collections;

import java.util.HashMap;

import java.util.HashSet;

import java.util.LinkedList;

import java.util.List;

import java.util.Map;

import java.util.Set;

import java.util.Stack;

public class Demo {

    private final Stack<Double> numStack = new Stack<Double>();

    private final Stack<Character> opStack = new Stack<Character>();

    private char currentOperator;

    private char opStackTop;

    private int i;

    private String expression;

    @SuppressWarnings("rawtypes")

    public void exec(String expression) {

        try {

            clean();

            if (expression == null || expression.isEmpty()) {

                throw new IllegalArgumentException("Blank Expression!");

            }

            this.expression = expression;

            opStack.push(TERMINATE_TOKENS.START_END_MARK);

            List tokens = TOKENIZER.exec(expression

                    + TERMINATE_TOKENS.START_END_MARK);

            for (; i < tokens.size(); i++) {

                final Object token = tokens.get(i);

                if (token instanceof Double) {

                    processOperand((double) token);

                } else {

                    processOperator((char) token);

                }

            }

        } catch (Throwable e) {

            System.err.println(String.format(

                    "Incorret Expression: %s\nError: %s", expression,

                    e.getMessage()));

        }

    }

    private void processOperand(final double operand) {

        numStack.push(operand);

    }

    private void processOperator(final char currentOperator) {

        this.currentOperator = currentOperator;

        this.opStackTop = opStack.peek();

        char calMode = CALCULATE_MODE.getRule(currentOperator, opStackTop);

        switch (calMode) {

        case '>':

            processStackHigerPriorityOperator();

            break;

        case '<':

            processStackLowerPriorityOperator();

            break;

        case '=':

            processStackEqualPriorityOperator();

            break;

        default:

            break;

        }

    }

    private void processStackLowerPriorityOperator() {

        opStack.push(currentOperator);

    }

    private void processStackHigerPriorityOperator() {

        numStack.push(CALCULATE.exec(opStack.pop(), numStack.pop(),

                numStack.pop()));

        --i; // pointer back to the previous operator.

    }

    private void processStackEqualPriorityOperator() {

        if (TERMINATE_TOKENS.START_END_MARK == currentOperator) {

            System.out.println(expression + " = " + numStack.peek());

        } else if (')' == currentOperator) {

            opStack.pop();

        }

    }

    public void clean() {

        numStack.clear();

        opStack.clear();

        i = 0;

    }

    public static void main(String[] args) {

        Demo cal = new Demo();

        cal.exec("1-2*((60-30+(40/5)*(9-2*5/3+7/3*99/4*2998 +10*568/14))-(4*3)/(16-3*2))"); // = -4.4

    }

}

enum CALCULATE {

    INSTANCE;

    public static double exec(final char operator, final double right,

            final double left) {

        switch (operator) {

        case '+':

            return left + right;

        case '-':

            return left - right;

        case '*':

            return left * right;

        case '/':

            return left / right;

        default:

            throw new IllegalArgumentException("Unsupported operator: "

                    + operator);

        }

    }

}

enum TERMINATE_TOKENS {

    INSTANCE;

    public static final char START_END_MARK = '#';

    private static final Map<Character, Integer> TOKENs = new HashMap<Character, Integer>();

    static {

        // token, token id

        TOKENs.put('+', 0);

        TOKENs.put('-', 1);

        TOKENs.put('*', 2);

        TOKENs.put('/', 3);

        TOKENs.put('(', 4);

        TOKENs.put(')', 5);

        TOKENs.put(START_END_MARK, 6);

    }

    private static Set<Character> NEGATIVE_NUM_SENSITIVE = new HashSet<Character>();

    public static synchronized Set<Character> getNegativeNumSensitiveToken() {

        if (NEGATIVE_NUM_SENSITIVE.size() == 0) {

            NEGATIVE_NUM_SENSITIVE.addAll(TOKENs.keySet());

            NEGATIVE_NUM_SENSITIVE.remove(')');

        }

        return NEGATIVE_NUM_SENSITIVE;

    }

    public static boolean isTerminateToken(final char token) {

        Set<Character> keys = TOKENs.keySet();

        return keys.contains(token);

    }

    public static int getTokenId(final char token) {

        return TOKENs.get(token) == null ? -1 : TOKENs.get(token);

    }

    public static int getTokenSize() {

        return TOKENs.size();

    }

}

enum CALCULATE_MODE {

    INSTANCE;

    private static char[][] RULES = {

            // + - * / ( ) #

            { '>', '>', '<', '<', '<', '>', '>' }, // +

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

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

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

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

            { '>', '>', '>', '>', 'o', '>', '>' }, // )

            { '<', '<', '<', '<', '<', 'o', '=' }, // #

    };

    static {

        if (RULES.length != TERMINATE_TOKENS.getTokenSize() || RULES.length < 1

                || RULES[0].length != TERMINATE_TOKENS.getTokenSize()) {

            throw new IllegalArgumentException("Rules matrix is incorrect!");

        }

    }

    public static char getRule(final char currentOperator, final char opStackTop) {

        try {

            return RULES[TERMINATE_TOKENS.getTokenId(opStackTop)][TERMINATE_TOKENS

                    .getTokenId(currentOperator)];

        } catch (Throwable e) {

            throw new RuntimeException("No rules were defined for some token!");

        }

    }

}

enum TOKENIZER {

    INSTANCE;

    private static final StringBuilder BUFFER = new StringBuilder();

    private static String clearExpression(String expression) {

        return expression.replaceAll(" ", "");

    }

    private static Character PREVIOUS_CHAR;

    private static void clean() {

        BUFFER.delete(0, BUFFER.length());

        PREVIOUS_CHAR = null;

    }

    private static boolean processNegativeNumbers(final String exp,

            final int index) {

        char c = exp.charAt(index);

        if (('+' == c || '-' == c)

                && (PREVIOUS_CHAR == null || TERMINATE_TOKENS

                        .getNegativeNumSensitiveToken().contains(PREVIOUS_CHAR))

                && !TERMINATE_TOKENS.isTerminateToken(exp.charAt(index + 1))) {

            BUFFER.append(c);

            return true;

        }

        return false;

    }

    @SuppressWarnings({ "unchecked", "rawtypes" })

    public static List<?> exec(final String expression) {

        clean();

        String exp = clearExpression(expression);

        List result = new LinkedList();

        for (int i = 0; i < exp.length(); i++) {

            char c = exp.charAt(i);

            if (TERMINATE_TOKENS.isTerminateToken(c)) {

                if (processNegativeNumbers(exp, i))

                    continue;

                if (BUFFER.length() > 0) {

                    result.add(Double.valueOf(BUFFER.toString()));

                    BUFFER.delete(0, BUFFER.length());

                }

                result.add(c);

            } else {

                BUFFER.append(c);

            }

            PREVIOUS_CHAR = c;

        }

        return Collections.unmodifiableList(result);

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: