java实现的带括号的计算器

  1 import java.math.BigDecimal;
  2 import java.util.ArrayList;
  3 import java.util.List;
  4 import java.util.Stack;
  5 import java.util.regex.Matcher;
  6 import java.util.regex.Pattern;
  7 
  8 
  9 public class Calu {
 10     private static List<String> sysboList=new ArrayList<String>(){{
 11         this.add("+");
 12         this.add("-");
 13         this.add("*");
 14         this.add("/");
 15         this.add("=");
 16     }};
 17     private static Pattern p1 = Pattern.compile("(^[0-9]{1,9}[.][0-9]{1,2}$)|(^[0-9]{1,11}$)");
 18     
 19     public static void main(String[] args) {
 20         String numstr="(2+2*(1+2))*3/2";
 21         System.out.println(result(numstr));
 22     }
 23     
 24     public static BigDecimal result(String numstr){
 25         //先把括号中的值给算出来然后替换,找的括号是最小范围的
 26         //最后一个'('出现的位置 到 第一个')'出现的位置
 27         StringBuffer sb=new StringBuffer(numstr);
 28         if(isStandard(sb.toString())){
 29             String rs=bracketsString(sb);
 30             while(rs!=null){
 31                 BigDecimal calBracketsValue = calBracketsValue(rs+"=");
 32                 sb.replace(sb.indexOf("@"), sb.indexOf("@")+1, calBracketsValue.toString());
 33                 System.out.println(sb);
 34                 rs=bracketsString(sb);
 35             }
 36             return calBracketsValue(sb.toString()+"=");
 37         }
 38         return new BigDecimal("0");
 39     }
 40     
 41     public static String bracketsString(StringBuffer str){
 42         int leftBracketsPoint=str.lastIndexOf("(");
 43         int rightBracketsPoint=str.indexOf(")");
 44         if(leftBracketsPoint==-1 || rightBracketsPoint==-1){
 45             return null;
 46         }
 47         String res= str.substring(leftBracketsPoint+1,rightBracketsPoint);
 48         str.replace(leftBracketsPoint, rightBracketsPoint+1, "@");
 49         return res;
 50     }
 51     
 52     //计算括号中的表达式的值
 53     public static BigDecimal calBracketsValue(String numStr){
 54         Stack<BigDecimal> numStack=new Stack<BigDecimal>();//数字栈
 55         Stack<String> sysmboStack=new Stack<String>();//符号栈
 56         int lastSysboPoint=0;//上一次非数字出现的位置
 57         for(int i=0;i<numStr.length();i++){
 58             String ch=numStr.charAt(i)+"";
 59             if(sysboList.contains(ch)){
 60                 //开始计算入栈
 61                 //先把前面的数字入栈 1+1*1=
 62                     String num=numStr.substring(lastSysboPoint,i);
 63                     numStack.push(new BigDecimal(num));
 64                 
 65                 while(!sysmboStack.isEmpty() && !comparePri(ch.charAt(0),sysmboStack.peek().charAt(0))){//如果符号栈不为空,就把前一个符号拿出来和现在的符号做优先级对比
 66                         BigDecimal num2=numStack.pop();
 67                         BigDecimal num1=numStack.pop();
 68                         String sysboTemp=sysmboStack.pop();
 69                         if(sysboTemp.equals("+")){
 70                             numStack.push(num1.add(num2));
 71                         }else if(sysboTemp.equals("-")){
 72                             numStack.push(num1.subtract(num2));
 73                         }else if(sysboTemp.equals("*")){
 74                             numStack.push(num1.multiply(num2));
 75                         }else if(sysboTemp.equals("/")){
 76                             numStack.push(num1.divide(num2,10,BigDecimal.ROUND_HALF_DOWN));
 77                         }
 78                 }
 79                 sysmboStack.push(ch);
 80                 lastSysboPoint=i+1;
 81             }
 82         }
 83         
 84         return numStack.pop();
 85     }
 86     
 87     
 88     
 89      private static boolean comparePri(char symbol,char top) {
 90             if (top == '(') {
 91                 return true;
 92             }
 93             // 比较优先级
 94             switch (symbol) { 
 95             case '(': // 优先级最高
 96                 return true;
 97             case '*': {
 98                 if (top == '+' || top == '-') // 优先级比+和-高
 99                     return true;
100                 else
101                     return false;
102             }
103             case '/': {
104                 if (top == '+' || top == '-') // 优先级比+和-高
105                     return true;
106                 else
107                     return false;
108             }
109             case '+':
110                 return false;
111             case '-':
112                 return false;
113             case ')': // 优先级最低
114                 return false;
115             case '=': // 结束符
116                 return false;
117             default:
118                 break;
119             }
120             return true;
121         }
122     
123      private static boolean isNumber(String num){
124             Matcher m1 = p1.matcher("123");   
125             return m1.matches();   
126      }
127      private static boolean isStandard(String numStr) {
128             if (numStr == null || numStr.isEmpty()) // 表达式不能为空
129                 return false;
130             Stack<Character> stack = new Stack<Character>(); // 用来保存括号,检查左右括号是否匹配
131             boolean b = false; // 用来标记'='符号是否存在多个
132             for (int i = 0; i < numStr.length(); i++) {
133                 char n = numStr.charAt(i);
134                 // 判断字符是否合法
135                 if (!(isNumber(n+"") || "(".equals(n + "") || ")".equals(n + "")
136                         || "+".equals(n + "") || "-".equals(n + "")
137                         || "*".equals(n + "") || "/".equals(n + "")
138                         || "=".equals(n + ""))) {
139                     return false;
140                 }
141                 // 将左括号压栈,用来给后面的右括号进行匹配
142                 if ("(".equals(n + "")) {
143                     stack.push(n);
144                 }
145                 if (")".equals(n + "")) { // 匹配括号
146                     if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配
147                         return false;
148                 }
149                 // 检查是否有多个'='号
150                 if ("=".equals(n + "")) {
151                     if (b)
152                         return false;
153                     b = true;
154                 }
155             }
156             // 可能会有缺少右括号的情况
157             if (!stack.isEmpty())
158                 return false;
159             return true;
160         }
161     
162 }

 

转载于:https://www.cnblogs.com/zxl550/p/9147383.html

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值