import java.util.Stack;
//
import java.util.regex.*;
import java.util.Stack;
/**
* This class use for get calculate result from the String expression
* we know that Java language have not class implement method calculate math
* expression, JavaScript have implement "eval".
* First get simple math expression, iteration wipe out brackets, get expression
* in brackets and format with priority, then insert result of formative expression
* into original expression, and simplify again
*
* Support operator "+", "-", "*", "/", "(", ")", "(-)"
* use Stack.RegEx
*
* @author Denua
* @version 07 May 2017 11.48
*/
public class Interpreter {
public static void main(String[] args) {
String s = "(1+2)-3*5+(5/5*5+5)-1/2";
Interpreter in = new Interpreter();
System.out.printf("%s = %g",s,in.elv(s));
}
/**
* public method as the entry
* @param str
* String expression
* @return
* double calculate result
*/
public double elv(String str){
double res = 0.00;
res = eval(formate(
getSimple(str)
)
);
return res;
}
/**
* return String simple expression without brackets,use RegEx check brackets and get
* result from the expression in the brackets
* @param str
* String complex expression
* @return String
* String simple expression
*/
private String getSimple(String str){
String res = str;
// RegEx matching the expression in brackets
Pattern pat2 = Pattern.compile("\\([\\d\\.\\+\\-\\*\\/]+\\)");
// matching
Matcher mat = pat2.matcher(str);
// if find matching, get simple expression result and joint to origin expression
if( mat.find() ){
String find = mat.group(0);
String st1 = res.substring(0, str.indexOf(find));
String st2 = res.substring(str.indexOf(find) + find.length(), res.length());
find = find.substring(1, find.length() - 1);
find = formate(find);
find = String.valueOf(eval(find));
res = st1 + find + st2;
// matching again and find expression in brackets, if find, get simple expression
Matcher mat2 = pat2.matcher(res);
if(mat2.find()){
res = getSimple(res);
}
}
return res;
}
/**
* add brackets for the simple String expression, complete priority, check
* each element in the expression
*
* @param str
* String simple expression
* @return String
* complete priority expression
*/
private String formate(String str){
String res = str;
String[][] part = getPart(res);
String[] pt = new String[part[0].length];
for(int q=0; q < pt.length; q++){
pt[q] = "";
}
int count = part[0].length;
int i = 0;
// all case in priority
// (*) *
// (+) +
// (*) +
// (+) *
// + * (*) +
// * (*) +
while( i < count){
String id= part[0][i];
String ir = null;
if(i < count - 1)
ir = part[0][i + 1];
if( nl(id) && nl(ir) ){
if( isf(id) ){
if( isf(ir) ){
pt[i+1] += ")";
}
else if( ! isf(ir) ){
pt[i+1] += ")";
int idx = i - 1;
while( idx >= 0 ){
String si = part[0][idx];
if( ! isf(si) ){
pt[i+1] = "))";
break;
}
idx--;
}
}
}
if( ! isf(id) ){
if( ! isf(ir) )
pt[i+1] += ")";
}
}
else if( nl(id) && ! nl(ir)){
if( isf(id) ){
int ix = i - 1;
boolean find = false;
while( ix >= 0 ){
String six = part[0][ix];
if( ! isf(six) ){
find = true;
break;
}
ix--;
}
if(find)
part[1][i+1] += "))";
else
part[1][i + 1] += ")";
}
else
part[1][i + 1] += ")";
}
else{
return null;
}
i++;
}
res = "";
for(int j = 0; j < part[0].length; j ++){
part[0][j] = pt[j] + part[0][j];
res =res + part[1][j] + part[0][j];
}
res += part[1][part[1].length -1];
return res;
}
/**
* use two Stack calculate expression with complete priority, one Stack
* save number another save operator, check each element in the expression
* with complete priority, if current element is number, then add to
* number Stack, if operator, add to operator Stack, else is ")" , extract
* two number from the number Stack, extract operator from the operator Stack
* and add result to number Stack, iteration get final result.
*
* @param str
* Complete priority expression
* @return double
* the result of the expression
*/
private Double eval(String str){
Stack<String> operate = new Stack<String>();
Stack<Double> value = new Stack<Double>();
String[] ele = getEle(str);
int i = 0;
while( i < ele.length){
String s = ele[i];
if(s.equals("(")){
}
else if(s.equals("+")) operate.push(s) ;
else if(s.equals("-")) operate.push(s) ;
else if(s.equals("*")) operate.push(s) ;
else if(s.equals("/")) operate.push(s) ;
else if(s.equals("s")) operate.push(s) ;
else if(s.equals(")")){
String op = operate.pop();
double vl = value.pop();
if(op.equals("+")) vl = value.pop() + vl;
else if(op.equals("-")) vl = value.pop() - vl;
else if(op.equals("*")) vl = value.pop() * vl;
else if(op.equals("/")) vl = value.pop() / vl;
else if(op.equals("s")) vl = Math.sqrt(vl);
value.push(vl);
}
else{
value.push(Double.parseDouble(s));
}
i++;
}
return value.pop();
}
/**
* get each part of the expression, cut expression and transform to Array
* @param str complete priority expression
* @return String[]
*/
private String[] getEle(String str){
Stack<String> st = new Stack<String>();
int j = 0;
String numbTemp = "";
while( j < str.length()){
char temp = str.charAt(j);
if( isNum(temp) || temp == '.' || ( j == 0 && temp == '-') || ( temp == '-' && isOp(str.charAt(j - 1)) ) ){
numbTemp += temp;
}
else if( ! isNum(temp) ){
if( !numbTemp.isEmpty()){
st.push(numbTemp);
numbTemp = "";
}
st.push(String.valueOf(temp));
}
j++;
}
String[] res = new String[st.size()];
for(int i = st.size() - 1; i >= 0; i -- ){
res[i] = st.pop();
}
return res;
}
private String[][] getPart(String str){
String res = str;
int i = 0;
Stack<String> cal = new Stack<String>();
Stack<String> op = new Stack<String>();
String num = "";
while( i < res.length()){
char temp = res.charAt(i);
if( isOp(temp) ){
if(temp == '-' && i == 0)
num += "-";
else if( temp == '-' && isOp(res.charAt(i-1)) )
num += "-";
else
op.push(String.valueOf(temp));
}
else if(isNum(temp)){
num += String.valueOf(temp);
if(i >= str.length()){
break;
}
else{
if( i == str.length() - 1){
String n = String.valueOf(str.charAt(i));
if( isNum(n) && isNum(String.valueOf(str.charAt(i-1)))){
num += n;
}
else{
num = n;
}
}
else{
String n = String.valueOf(str.charAt(i + 1));
boolean flag = true;
while( isNum(n) && flag){
num += n;
i ++;
if( i > res.length() - 2){
flag = false;
}else{
n = String.valueOf(str.charAt(i + 1));
}
}
}
}
cal.push(num);
num = "";
}
else if(temp == ')'){
op.push(")");
}
i++;
}
i = 0;
String[][] part = new String[2][];
String[] temp1 = new String[op.size()];
String[] temp2 = new String[cal.size()];
for(Object o:op.toArray()){
temp1[i] = (String) o;
i++;
}
i = 0;
for(Object o:cal.toArray()){
temp2[i] = (String) o;
i++;
}
part[0] = temp1;
part[1] = temp2;
return part;
}
private boolean isNum(String str){
return str.equals("0") || str.equals("1") || str.equals("2") || str.equals("3") || str.equals("4") ||
str.equals("5") || str.equals("6") || str.equals("7") || str.equals("8") || str.equals("9") || str.equals(".");
}
private boolean isOp(char str){
return str == 's' || str == '+' ||str == '-' || str == '*' || str == '/' ;
}
private boolean isNum(char str){
return str == '0' || str == '1' || str == '2' || str == '3' || str == '4' ||
str == '5' || str == '6' || str == '7' || str == '8' || str == '9' || str == '.' ;
}
private boolean isf(String str){
return str.equals("*") || str.equals("/");
}
private boolean nl(Object obj){
return obj != null;
}
}
转载于:https://blog.51cto.com/12893274/1922908