计算表达式的计算
import org.junit.Test;
import java.util.Arrays;
import java.util.Stack;
/**
* 计算表达式的计算
* Created by Relish on 2016/8/14.
*/
public class CalculateUtil {
@Test
public void test () {
String exp = "10+2*3/(4-5.0)" ;
System.out.println(calculate(exp));
}
private static final String REGEX_NUM = "[0-9]+|([0-9]+\\.[0-9]+)" ;
private static int [] value = new int [50 ];
static {
value['+' ] = 0 ;
value['-' ] = 0 ;
value['*' ] = 1 ;
value['/' ] = 1 ;
value['(' ] = 2 ;
value[')' ] = -1 ;
}
public String calculate (String rawExp) {
String[] postfixExp = infix2Postfix(rawExp);
System.out.println("后缀:" + Arrays.toString(postfixExp));
Stack<String> numStack = new Stack<>();
for (String s : postfixExp) {
if (s.matches(REGEX_NUM)) {
numStack.push(s);
} else {
if (numStack.size() == 1 ) {
return numStack.pop();
}
double n2 = Double.parseDouble(numStack.pop());
double n1 = Double.parseDouble(numStack.pop());
switch (s.charAt(0 )) {
case '+' :
numStack.push((n1 + n2) + "" );
break ;
case '-' :
numStack.push((n1 - n2) + "" );
break ;
case '*' :
numStack.push((n1 * n2) + "" );
break ;
case '/' :
if (n2 == 0 ) {
System.err.println("除数不能为0!" );
return null ;
}
numStack.push((n1 / n2) + "" );
break ;
}
}
}
return numStack.pop();
}
/**
* 中缀转后缀
*
* @param rawExp 中缀表达式
* @return 后缀表达式
*/
private static String[] infix2Postfix (String rawExp) {
if (!isExpressionLegitimate(rawExp)) {
System.err.println("非法计算表达式!" );
return null ;
}
Stack<Character> opStack = new Stack<>();
String[] splitExp = split(rawExp);
System.out.println("切割:" + Arrays.toString(splitExp).replaceAll("[\\[\\]]" , "" ).replace(", " , " " ));
Stack<String> postfixStack = new Stack<>();
for (String s : splitExp) {
if (s.matches(REGEX_NUM)) {
postfixStack.push(s);
} else if (s.length() == 1 && isCharacterLegitimate(s.charAt(0 ))) {
char op = s.charAt(0 );
if (opStack.isEmpty()) {
opStack.push(op);
} else {
if (isSimpleOperator(op) || op == '(' ) {
if (value[op] > value[opStack.peek()] || op == '(' ) {
opStack.push(op);
} else {
while ((!opStack.isEmpty()) && value[op] <= value[opStack.peek()]) {
char c = opStack.peek();
if (c == '(' ) {
break ;
} else {
postfixStack.push(opStack.pop() + "" );
}
}
opStack.push(op);
}
} else {
while ((!opStack.isEmpty())) {
char c = opStack.peek();
if (c == '(' ) {
opStack.pop();
break ;
} else {
postfixStack.push(c + "" );
opStack.pop();
}
}
}
}
}
}
while (!opStack.isEmpty()) {
postfixStack.push(opStack.pop() + "" );
}
String[] postfix = new String[postfixStack.size()];
int i = postfix.length;
while (!postfixStack.isEmpty()) {
postfix[--i] = postfixStack.pop();
}
return postfix;
}
/**
* 将运算符(包含左右括号)、数字分割成字符串数组
*
* @param rawExp 计算表达式
* @return 字符串数组
*/
private static String[] split (String rawExp) {
StringBuilder sb = new StringBuilder();
for (char c : rawExp.toCharArray()) {
if (isCharacterLegitimate(c)) {
sb.append("," );
sb.append(c);
sb.append("," );
} else {
sb.append(c);
}
}
return sb.toString().replaceAll(",{2}" , "," ).split("," );
}
/**
* 括号是否匹配
*
* @param exp 计算表达式
* @return 匹配与否
*/
private static boolean isBracketsMatching (String exp) {
Stack<Character> stack = new Stack<>();
for (char c : exp.toCharArray()) {
if (c == '(' ) {
stack.push(c);
} else if (c == ')' ) {
if (stack.peek() == '(' ) {
stack.pop();
} else {
return false ;
}
}
}
return stack.isEmpty();
}
/**
* 计算法表达式是否合法
*
* @param exp 计算表达式
* @return 合法与否
*/
private static boolean isExpressionLegitimate (String exp) {
if (exp.contains("(" ) && exp.contains(")" ) && isBracketsMatching(exp)) {
int start = exp.indexOf("(" );
int end = exp.lastIndexOf(")" );
return isExpressionLegitimate(exp.substring(start + 1 , end)) &&
isExpressionLegitimate(exp.substring(0 , start) + "0" +
(end + 1 >= exp.length() ? "" : exp.substring(end + 1 )));
} else {
return exp.matches("^([0-9]+|([0-9]+\\.[0-9]+))([+\\-*/]([0-9]+|([0-9]+\\.[0-9]+)))*$" );
}
}
/**
* 是否是+、-、*、/中的任何一个字符
*
* @param ch 字符
* @return 匹配与否
*/
private static boolean isSimpleOperator (char ch) {
return ch == '+' || ch == '-' || ch == '*' || ch == '/' ;
}
/**
* 是否是合法字符:+、-、*、/、(、)
*
* @param ch 字符
* @return 合法与否
*/
private static boolean isCharacterLegitimate (char ch) {
return ch == '(' || ch == ')' || isSimpleOperator(ch);
}
}