1. 程式人生 > >表達式計算

表達式計算

etop turn rect sub 1.8 push bre private args

package algorithm.other;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.Map.Entry;

/**
* 表達式計算
* 支持帶括號的+、-、*、/運算
* @author NINGUANG
*
*/
public class ExpressionCal
{
private Map<Character,String> map= new HashMap<Character,String>();

private String sorce;

/**
* 轉成後綴表達式
* @param sorce
* @return
*/
private String convertPostfix(String sorce)
{
String desk = "";
Stack<Character> stack = new Stack<Character>();
for(int i=0;i<sorce.length();i++)
{
char ch = sorce.charAt(i);
switch(ch)
{
case ‘+‘:
case ‘-‘:
desk = getOperator(stack,ch,1,desk);
break;
case ‘*‘:
case ‘/‘:
desk = getOperator(stack,ch,2,desk);
break;
// case ‘^‘:
// desk = getOperator(stack,ch,3,desk);
// break;
case ‘(‘:
stack.push(ch);
break;
case ‘)‘:
desk = getParenthesis(stack,ch,desk);
break;
default:
desk = desk + ch;
}
}
while(!stack.isEmpty())
{
desk = desk + stack.pop();
}
return desk;
}

private String getParenthesis(Stack<Character> stack, char ch, String desk)
{
while(!stack.isEmpty())
{
char top = stack.pop();
if(top == ‘(‘)
{
break;
}else
{
desk = desk + top;
}

}
return desk;
}

private String getOperator(Stack<Character> stack, char ch, int precIn, String desk)
{
while(!stack.isEmpty())
{
char top = stack.pop();
if( top == ‘(‘)
{
stack.push(top); //(2+或(2*情況 ,優先級在後面,先壓入棧(+或(*
break;
}
else
{
int precTop;
if(top == ‘+‘ || top == ‘-‘)
{
precTop = 1;
}
else
{
precTop = 2;
}
if(precTop < precIn)
{
stack.push(top); // 2+3*情況,優先級在後面,先壓入棧+*
break;
}
else
{
desk = desk + top; //2*3+情況 或 2+3+情況,生成23*或23+
}
}

}
stack.push(ch);
return desk;
}

/**
* 放入表達式
* @param sorce
* @return 變量列表
*/
public List<String> setExpression(String sorce)
{

map.clear();
List<String> vars = new ArrayList<String>();
StringBuffer buff = new StringBuffer();
int varNum = 0;
for (int i = 0; i<sorce.length();i++)
{
char ch = sorce.charAt(i);
if(ch!=‘+‘&&ch!=‘-‘&&ch!=‘*‘&&ch!=‘/‘&&ch!=‘(‘&&ch!=‘)‘)
{
buff.append(ch);
}
else if(buff.length()>0)
{
if(!vars.contains(buff.toString()))
{
vars.add(buff.toString());
map.put((char)(‘a‘+varNum), buff.toString());
varNum++;
}
buff.setLength(0);
}
}
if(buff.length()>0)
{
if(!vars.contains(buff.toString()))
{
vars.add(buff.toString());
map.put((char)(‘a‘+varNum), buff.toString());
}
}

for (Entry<Character, String> entry : map.entrySet())
{
sorce = sorce.replaceAll(entry.getValue(), entry.getKey()+"");
}
this.sorce = sorce;
// System.out.println(sorce);
// System.out.println(map);
return vars;
}

/**
* 表達式計算
* @param feemap 變量--數值映射
* @param scale 保留位數
* @return 計算結果
*/
public String calculate(Map<String, BigDecimal> feemap,int scale)
{
String tempResult = convertPostfix(sorce);
String result = calculatePostfix(tempResult,feemap,scale);
return result;
}

/**
* 計算後綴表達式
* @param tempResult
* @return
*/
private String calculatePostfix(String tempResult,Map<String, BigDecimal> feemap,int scale)
{
Stack<BigDecimal> stack = new Stack<BigDecimal>();
BigDecimal temp;
for (int i=0;i<tempResult.length();i++)
{
char ch = tempResult.charAt(i);
if(ch>=‘a‘&& ch<=‘z‘)
{
stack.push(feemap.get(map.get(ch)));
}
else
{
BigDecimal num2 = stack.pop();
BigDecimal num1 = stack.pop();
switch(ch)
{
case ‘+‘:
temp = num1.add(num2);
break;
case ‘-‘:
temp = num1.subtract(num2);
break;
case ‘*‘:
temp = num1.multiply(num2);
break;
case ‘/‘:
temp = num1.divide(num2, 6, BigDecimal.ROUND_HALF_UP);
break;
// case ‘^‘:
// temp = num1.pow(num2.intValue());
// break;
default:
temp = new BigDecimal(0);
}
stack.push(temp);
}
}
if(scale==0)
{
return stack.pop().intValue()+"";
}
else
{
return stack.pop().setScale(scale).toString();
}
}

public static void main(String[] args)
{
ExpressionCal ec = new ExpressionCal();
List<String> list = ec.setExpression("(審定.靜態投資-送審.靜態投資)/(審定.動態投資-送審.動態投資)");
System.out.println(list);
Map<String, BigDecimal> feemap = new HashMap<String, BigDecimal>();
feemap.put("審定.靜態投資", new BigDecimal(801.82));
feemap.put("送審.靜態投資", new BigDecimal(400.42));
feemap.put("審定.動態投資", new BigDecimal(202));
feemap.put("送審.動態投資", new BigDecimal(200));
System.out.println("計算結果:"+ec.calculate(feemap,1));
}
}

表達式計算