java实现的带括号的计算器

Wesley13
• 阅读 676
  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 }
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
3年前
Docker 部署SpringBoot项目不香吗?
  公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上角,将我们设为★“星标”!这样才不会错过每日进阶架构文章呀。  !(http://dingyue.ws.126.net/2020/0920/b00fbfc7j00qgy5xy002kd200qo00hsg00it00cj.jpg)  2
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这