策码奔腾

利用栈实现表达式计算

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 CEMABENTENG
*
*/
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));
}
}

posted @ 2017-05-18 13:43  策码奔腾  阅读(563)  评论(0编辑  收藏  举报
console.log('欢迎');