import java.util.Stack;
import java.util.StringTokenizer;
/**
* 逆波兰式计算
* java 运算公式运算得出结果 可以计算负数,保留小数位数
* @Date: 2018/9/6 11:41
* @Description:
*/
public class ReversePolishCalculate {
private static final int One = 1; //规定优先级 最低
private static final int Two = 2; //
private static final int Three = 3; //规定优先级 Three 最高
private static final int SCALE = 10; //保留小数位数
/**
* 计算 逆波兰式
* @param formulaStr
* @return
* @throws Exception
*/
public static String reversePolishCalculate(String formulaStr) throws Exception {
Stack<String> ysStack = new Stack<>(); // 定义一个运算栈
ArrayList<String> nblbdsList = zzHz(formulaStr);//得到逆波兰后缀
for(String nblbdsStr:nblbdsList){
if(isNum(nblbdsStr)){
ysStack.push(nblbdsStr);
}else{
ysStack.push(String.valueOf(calculate(ysStack.pop(), ysStack.pop(), nblbdsStr)));
}
}
return ysStack.pop(); //最后 栈中元素 即为结果
}
/**
* 判断 是否是数字
* @param str
* @return
*/
public static boolean isNum(String str){
if(str.matches("([1-9]\\d*\\.?\\d*)|(0\\.\\d*[0-9])|(0)")){ //这里使用正则表达式 验证是否是数字包含小数,0
return true;
}
return false;
}
/**
* 判断 是否是操作符
* @param str
* @return
*/
public static boolean isCzf(String str){
switch(str){
case "(":
case "*":
case "/":
case "+":
case "-":
case ")":return true;
default : return false;
}
}
/**
* 获取 优先级
* @param str
* @return
*/
private static int getYxj(String str){
switch(str){
case "(":return Three;
case "*":
case "/":return Two;
case "+":
case "-":return One;
case ")":return 0;
default : return -1;
}
}
/**
* 判断优先级
* @param str1
* @param str2
* @return
*/
private static boolean isYxj(String str1,String str2){
return getYxj(str1) > getYxj(str2);
}
/**
* 数字直接入nblbdsList
* 运算符要与operators栈顶比较,优先级大则入栈,小于或等于但不是)则operators出栈到(后该操作符再入栈,如果是)则到(之后
* operators栈顶若是(则无条件入栈
* ********* 当 当前操作元素为 操作符时********** 这里是 核心代码, 用于操作符栈的判断
* @param czf
* @param nblbdsList
* @param czfStack
*/
private static void stackCzf(String czf,ArrayList<String> nblbdsList,Stack<String> czfStack){
//判断当前栈内是否为空
if(czfStack.isEmpty()){
czfStack.push(czf);
return;
}
//判断是否为 (
if("(".equals(czf)){
czfStack.push(czf);
return;
}
//判断是否为 )
if(")".equals(czf)){
String string = "";
while(!"(".equals(string = czfStack.pop())){
nblbdsList.add(string);
}
return;
}
//如果 当前栈顶元素是 ( 直接入栈
if("(".equals(czfStack.peek())){
czfStack.push(czf);
return;
}
// 判断 与 栈顶元素的优先级 , > 为true
if(isYxj(czf, czfStack.peek())){
czfStack.push(czf);
return;
}
if(!isYxj(czf, czfStack.peek())){
nblbdsList.add(czfStack.pop());
stackCzf(czf,nblbdsList,czfStack); //这里调用函数 本身,并将本次的操作数传参
}
}
/**
*
* 逆波兰转换
* 中缀 —> 后缀
* @param formulaStr
* @return
* @throws Exception
*/
private static ArrayList<String> zzHz(String formulaStr) throws Exception {
ArrayList<String> nblbdsList = new ArrayList<>(); // 存放转换后的 逆波兰式
Stack<String> czfStack = new Stack<>(); // 存放 运算符的栈
StringTokenizer stringTokenizer = new StringTokenizer(formulaStr, " +-*/()",true);
Boolean preFlag = false;
while(stringTokenizer.hasMoreTokens()) { //字符串分割
String currStr = stringTokenizer.nextToken();
if(isNum(currStr)){
nblbdsList.add(currStr);
preFlag = false;
continue;
}
if(isCzf(currStr)){
if("-".equals(currStr)&&preFlag){
nblbdsList.add("0");
}
stackCzf(currStr,nblbdsList,czfStack);
preFlag = true;
continue;
}
if(" ".equals(currStr)){
continue;
}
throw new Exception("非法字符:"+currStr);
}
// 遍历完原始表达式后 将操作符栈内元素 全部添加至 逆波兰表达式list
while(!czfStack.isEmpty()){
nblbdsList.add(czfStack.pop());
}
return nblbdsList;
}
/**
* 具体计算方法
* @param s1
* @param s2
* @param s3
* @return
*/
private static BigDecimal calculate(String s1, String s2, String s3){
BigDecimal one= new BigDecimal(s2);
BigDecimal two= new BigDecimal(s1);
switch(s3){
case "+":return one.add(two);
case "-":return one.subtract(two);
case "*":return one.multiply(two);
case "/":return one.divide(two,SCALE,BigDecimal.ROUND_HALF_UP);
default : return BigDecimal.ZERO;
}
}
public static void main(String[] ars){
try {
String a= ReversePolishCalculate.reversePolishCalculate("1+(1+1.5)");
System.out.println(a);
} catch (Exception e) {
e.printStackTrace();
}
}
}
原文:https://www.cnblogs.com/wushenghfut/p/12637396.html