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);
}
}
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);
}
}
相关文章推荐
- eclipse中JS文件乱码
- jstl与struts2 条件语句的区别
- springmvc + quartz任务调度执行多次问题
- struts2学习前的准备
- MyEclipse 10中各种Libraries的含义
- Eclipse或myeclipse安装jbpm6.3插件
- springmvc之数据格式化
- 使用 Spring Data JPA 简化 JPA 开发
- struts2-通过action从后台将json数据传到前台的方法(一)
- 在Java中wait、notify和notifyAll是如何工作的
- Java栈
- Struts2的运行原理(配图解)
- The Java™ Tutorials — Generics :Wildcards 通配符
- javaweb第二弹--不使用eclipse开发Servlet
- Java写了main()方法运行时在类 class 中找不到 main 方法
- 在Java API设计中,面向接口编程的思想,以及接口和工厂的关系
- java 泛型 E/T/K/V/N 代表的意义
- springmvc:jsp fmt标签格式化Date时间,格式化后可以用于页面展示或者提交给后台
- 在Java代码中使用pdfBox将PDF转换为图片
- 在Java代码中使用iTextPDF生成PDF