四则运算的中缀转后缀,逆波兰表达式求值

首先描述问题
[code]
给定一个字符串
example:"4-(4-3*5+(2*4)+100)/10";
要求输出结果"-5.70";结果四舍五入,保留两位小数
[/code]
首先进行的是括号优先级的处理
[code]
public BigDecimal calculateString(String str) {
char[] strs = str.toCharArray();
Stack<String> stack = new Stack<String>();

for (int i = 0; i < strs.length; i++) {
String stackStr = String.valueOf(strs[i]);
stack.push(stackStr);
if (")".equals(stack.top())) {
String subStr = null;
while (!"(".equals(stack.top())) {
stack.pop();
if (!"(".equals(stack.top())) {
subStr = addEnd(subStr, stack.top());
}
}
String pushStr = CalculateReversePolishExpression(subStr);
stack.pop();
stack.push(pushStr);
}

}
String resultStr = null;
while (stack.count != 0) {
resultStr = CalculateReversePolishExpression(stack.toString());
}
BigDecimal result = null;
if (resultStr != null) {
result = new BigDecimal(resultStr);
} else {
result = BigDecimal.ZERO;
}
return result.setScale(2, BigDecimal.ROUND_HALF_UP);
}
[/code]
将每个字符逐一进栈,当扫描到")"时,进行出栈操作,直到栈顶元素等于"("
并记录出栈的"("与")"之间的字符串为subStr
然后是对subStr求后缀表达式,并计算结果
也就是这句代码
[code]
String pushStr = CalculateReversePolishExpression(subStr);
[/code]
再把结果进栈
最后stack的内容是去掉括号的一个四则表达式
再进行一次CalculateReversePolishExpression方法,则得到最终结果

中缀转后缀表达式的基本思路
基本思路如下:
用一个链表 List<String> 储存将要生成的后缀表达式
用一个栈 Stack<String> 储存操作符
判断当前节点, 如果是操作数, 直接加入后缀表达式中, 如果是操作符,则比较前一个操作符和当前操作符的优先级,
如果前一个操作符优先级较高,则将前一个操作符加入后缀表达式中,否则将操作符压入操作符栈,如果遇到反括号 ')', 则在操作符栈中反向搜索,直到遇到匹配的正括号为止,将中间的操作符依次加到后缀表达式中。

然后是后缀表达式的计算

遍历储存后缀表达式的链表,将元素依次进栈,当遇到操作符时,连续出栈两个元素,进行运算,再将结果进栈,最后栈内留下的元素就是计算结果

最后再贴出茫茫多的代码
[code]
package graph;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* 应用:逆波兰表达式
*
* @author Leon.Chen
*
*/
public class CalculateString {

public BigDecimal calculateString(String str) {
char[] strs = str.toCharArray();
Stack<String> stack = new Stack<String>();

for (int i = 0; i < strs.length; i++) {
String stackStr = String.valueOf(strs[i]);
stack.push(stackStr);
if (")".equals(stack.top())) {
String subStr = null;
while (!"(".equals(stack.top())) {
stack.pop();
if (!"(".equals(stack.top())) {
subStr = addEnd(subStr, stack.top());
}
}
String pushStr = CalculateReversePolishExpression(subStr);
stack.pop();
stack.push(pushStr);
}

}
String resultStr = null;
while (stack.count != 0) {
resultStr = CalculateReversePolishExpression(stack.toString());
}
BigDecimal result = null;
if (resultStr != null) {
result = new BigDecimal(resultStr);
} else {
result = BigDecimal.ZERO;
}
return result.setScale(2, BigDecimal.ROUND_HALF_UP);
}

public String[] matcher(String regex, String str) {
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(str);
List<String> list = new ArrayList<String>();
while (matcher.find()) {
list.add(matcher.group());
}
String[] result = new String[list.size()];
return list.toArray(result);
}

public List<String> createReversePolishExpression(String subStr) {
String regex = "\\d+\\.{0,1}\\d*";
String[] numbers = matcher(regex, subStr);
String changeStr = subStr.replaceAll(regex, "0").replaceAll("\\-\\-0",
"-1").replaceAll("\\+\\-0", "+1").replaceAll("\\*\\-0", "*1")
.replaceAll("\\/\\-0", "/1");
char[] chars = changeStr.toCharArray();
int index = 0;
List<String> list = new ArrayList<String>();
for (int i = 0; i < chars.length; i++) {
String str = String.valueOf(chars[i]);
if ("0".equals(str)) {
list.add(numbers[index++]);
} else if ("1".equals(str)) {
list.add("-" + numbers[index++]);
} else {
list.add(str);
}
}
List<String> suffix = new ArrayList<String>();
Stack<String> operator = new Stack<String>();
for (int i = 0; i < list.size(); i++) {
if (!isOperatorType(list.get(i))) {
suffix.add(list.get(i));
} else {
if (operator.count == 0) {
operator.push(list.get(i));
} else {
while (operator.count != 0&&compare(operator.top(), list.get(i)) >= 0) {
String top = operator.top();
operator.pop();
suffix.add(top);
}
operator.push(list.get(i));

}
}
}

while (operator.count != 0) {
suffix.add(operator.top());
operator.pop();
}
return suffix;
}

public String CalculateReversePolishExpression(String subStr) {
List<String> suffix = createReversePolishExpression(subStr);
Stack<Double> stack = new Stack<Double>();
for (int i = 0; i < suffix.size(); i++) {
if (!isOperatorType(suffix.get(i))) {
stack.push(Double.valueOf(suffix.get(i)));
} else {
Double current = stack.top();
stack.pop();
Double previous = null;
if (stack.count != 0) {
previous = stack.top();
stack.pop();
} else {
previous = new Double(0);
}
Double result = calculate(suffix.get(i), previous, current);
stack.push(result);
}
}
return stack.top().toString();
}

public String addEnd(String str, String a) {
StringBuffer buf = new StringBuffer();
buf.append(a);
if (str != null) {
buf.append(str);
}
return buf.toString();
}

public boolean isOperatorType(String str) {
if (str.equals("+") || str.equals("-") || str.equals("*")
|| str.equals("/")) {
return true;
}
return false;
}

public int compare(String op1, String op2) {
Integer iop1 = getOperator(op1);
Integer iop2 = getOperator(op2);
return iop1.compareTo(iop2);
}

public Integer getOperator(String op) {
if ("+".equals(op) || "-".equals(op)) {
return new Integer(0);
}
if ("*".equals(op) || "/".equals(op)) {
return new Integer(1);
}
return null;
}

public Double calculate(String op, Double previous, Double current) {
if ("+".equals(op)) {
return previous + current;
}
if ("-".equals(op)) {
return previous - current;
}
if ("*".equals(op)) {
return previous * current;
}
if ("/".equals(op)) {
return previous / current;
}
return null;
}

public static void main(String[] args) {
String[] strs = new String[]{"(5+6)*7","(-1)/(-3)","1/(-3)","-1/7","7+(3*5)-(8+20/2)","4-(4-3*5+(2*4)+100)/10"};
for(int i=0;i<strs.length;i++){
BigDecimal result = new CalculateString().calculateString(strs[i]);
System.out.println(result.toString());
}

}

}

[/code]
自己写的stack

[code]
package graph;

public class Stack<T> {
public StackNode<T> stackTop;
public int count;
public void push(T info) {
StackNode<T> node = new StackNode<T>();
node.info = info;
node.link = stackTop;
stackTop = node;
count++;
}

public void pop() {
if(stackTop == null) {
System.out.println("null stack");
} else {
stackTop = stackTop.link;
count--;
}

}

public boolean isEmpty() {
return count == 0;
}

public T top() {
if(stackTop == null) {
return null;
}
return stackTop.info;
}

public String toString(){
Stack<T> other = new Stack<T>();
while(count != 0){
T top = top();
pop();
other.push(top);
}
StringBuffer buf = new StringBuffer();
while(other.count !=0){
buf.append(other.top());
other.pop();
}
return buf.toString();
}

}

[/code]
stack节点
[code]
package graph;

public class StackNode<T> {
public StackNode<T> link;
public T info;
}

[/code]

懒得copy的话下载附件
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/* 表达式计算 */ /* 调用方式:CalcExp('1+max(0.5,sin(1))+sum(1,2^3,mod(5,3))', res, infoStr) */ /* 带符号参数调用方法,先调用符号定义AddSignParam,再调用 CalcExp: */ /* AddSignParam(['a','s'], [1, 0.5]); 或者 AddSignParam('a=1,s=0.5') */ /* CalcExp('1+a+sin(s)', res, infoStr) */ /* 其中res存储计算结果,为double型;infoStr存储计算时的提示信息,为string */ 表达式计算器 V2.3 支持以下功能: 1、四则运算 + - * / 、括弧()、正负(+ -) 2、百分数 %、幂 ^ 、整数阶乘 ! (1 至 150) 3、参数符号计算,示例:a+b @@a=1,b=2 结算结果为3 用@@表示表达式中定义符号的 4、常数e、圆周率PI 5、丰富的函数功能: 统计函数: max,min,sum,avg,stddev 标准偏差,均支持多参数 三角函数: sin,cos,tan,arcsin,arccos,arctan degrad(60) 角度弧度 raddeg(3.14) 弧度角度 costh(a,b,c) 余弦定理 cosC) 指数对数函数:sqrt,power(x,y),abs,exp,log2,log10,logN(a,N),ln 数据处理函数:int(x),trunc(x) 取整 frac(x) 取小数部分 round(x) 四舍五入取整 roundto(x,-1) 保留一位小数 mod(M,N) 模 几何面积函数:s_tria(a,b,c) 三角形面积 s_circ(r) 圆形面积 s_elli(a,b) 椭圆面积 s_rect(a,b) 矩形面积 s_poly(a,n) 正多边形面积 平面几何函数:pdisplanes(x1,y1,x2,y2) 平面两点距离 pdisspace(x1,y1,z1,x2,y2,z2) 空间两点 p_line(x0,y0, A, B, C) 平面点到线距离 p_planes(x0,y0,z0 A, B, C, D)空间点到面距离 数列和: sn(a1, d, n) 等差数列前n项和 sqn(a1, q, n) 等比数列前n项和 个税计算函数:intax(x), arcintax(x) 个税反算 6 、历史计算记录,双击计算记录可重新修改计算 示例: sin(1)+(-2+(3-4))*20% , e^63+PI , 15! , log2(max(2,3)) 注: 运算符必须为半角格式,三角函为弧度,输入可用空格间隔

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值