java 括号计算_Java实现带括号优先级的计算器

这个Java程序实现了一个支持括号和四则运算的计算器。它使用两个栈来处理数字和运算符,包括括号的优先级计算。通过解析表达式,将数字压入数字栈,遇到运算符或括号时进行相应的操作。程序还包含检查表达式合法性、去括号和比较运算符优先级的辅助功能。
摘要由CSDN通过智能技术生成

这个计算器不仅能够进行四则运算,还支持添加括号进行优先级计算,例如下面算式:

10+(2*16-20/5)+7*2=52

Java源代码:

1 importjava.awt.BorderLayout;2 importjava.awt.Container;3 importjava.awt.event.ActionEvent;4 importjava.awt.event.ActionListener;5 importjava.util.Stack;6

7 importjavax.swing.JButton;8 importjavax.swing.JFrame;9 importjavax.swing.JLabel;10 importjavax.swing.JPanel;11 importjavax.swing.JTextField;12

13 /**

14 * 计算器15 */

16 public classCalculator {17

18 /**数字栈:用于存储表达式中的各个数字*/

19 private Stack numberStack = null;20 /**符号栈:用于存储运算符和括号*/

21 private Stack symbolStack = null;22

23 /**

24 * 解析并计算四则运算表达式(含括号),返回计算结果25 *26 *@paramnumStr27 * 算术表达式(含括号)28 */

29 public longcaculate(String numStr) {30 numStr = removeStrSpace(numStr); //去除空格31 //如果算术表达式尾部没有‘=’号,则在尾部添加‘=’,表示结束符

32 if (numStr.length() > 1 && !"=".equals(numStr.charAt(numStr.length() - 1) + "")) {33 numStr += "=";34 }35 //检查表达式是否合法

36 if (!isStandard(numStr)) {37 System.err.println("错误:算术表达式有误!");38 return 0;39 }40 //初始化栈

41 numberStack = new Stack();42 symbolStack = new Stack();43 //用于缓存数字,因为数字可能是多位的

44 StringBuffer temp = newStringBuffer();45 //从表达式的第一个字符开始处理

46 for (int i = 0; i < numStr.length(); i++) {47 char ch = numStr.charAt(i); //获取一个字符

48 if (isNumber(ch)) { //若当前字符是数字

49 temp.append(ch); //加入到数字缓存中

50 } else { //非数字的情况

51 String tempStr = temp.toString(); //将数字缓存转为字符串

52 if (!tempStr.isEmpty()) {53 long num = Long.parseLong(tempStr); //将数字字符串转为长整型数

54 numberStack.push(num); //将数字压栈

55 temp = new StringBuffer(); //重置数字缓存

56 }57 //判断运算符的优先级,若当前优先级低于栈顶的优先级,则先把计算前面计算出来

58 while (!comparePri(ch) && !symbolStack.empty()) {59 long b = numberStack.pop(); //出栈,取出数字,后进先出

60 long a =numberStack.pop();61 //取出运算符进行相应运算,并把结果压栈进行下一次运算

62 switch ((char) symbolStack.pop()) {63 case '+':64 numberStack.push(a +b);65 break;66 case '-':67 numberStack.push(a -b);68 break;69 case '*':70 numberStack.push(a *b);71 break;72 case '/':73 numberStack.push(a /b);74 break;75 default:76 break;77 }78 } //while循环结束

79 if (ch != '=') {80 symbolStack.push(new Character(ch)); //符号入栈

81 if (ch == ')') { //去括号

82 symbolStack.pop();83 symbolStack.pop();84 }85 }86 }87 } //for循环结束

88

89 return numberStack.pop(); //返回计算结果

90 }91

92 /**

93 * 去除字符串中的所有空格94 */

95 privateString removeStrSpace(String str) {96 return str != null ? str.replaceAll(" ", "") : "";97 }98

99 /**

100 * 检查算术表达式的基本合法性,符合返回true,否则false101 */

102 private booleanisStandard(String numStr) {103 if (numStr == null || numStr.isEmpty()) //表达式不能为空

104 return false;105 Stack stack = new Stack(); //用来保存括号,检查左右括号是否匹配

106 boolean b = false; //用来标记'='符号是否存在多个

107 for (int i = 0; i < numStr.length(); i++) {108 char n =numStr.charAt(i);109 //判断字符是否合法

110 if (!(isNumber(n) || "(".equals(n + "") || ")".equals(n + "")111 || "+".equals(n + "") || "-".equals(n + "")112 || "*".equals(n + "") || "/".equals(n + "")113 || "=".equals(n + ""))) {114 return false;115 }116 //将左括号压栈,用来给后面的右括号进行匹配

117 if ("(".equals(n + "")) {118 stack.push(n);119 }120 if (")".equals(n + "")) { //匹配括号

121 if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) //括号是否匹配

122 return false;123 }124 //检查是否有多个'='号

125 if ("=".equals(n + "")) {126 if(b)127 return false;128 b = true;129 }130 }131 //可能会有缺少右括号的情况

132 if (!stack.isEmpty())133 return false;134 //检查'='号是否不在末尾

135 if (!("=".equals(numStr.charAt(numStr.length() - 1) + "")))136 return false;137 return true;138 }139

140 /**

141 * 判断字符是否是0-9的数字142 */

143 private boolean isNumber(charnum) {144 if (num >= '0' && num <= '9')145 return true;146 return false;147 }148

149 /**

150 * 比较优先级:如果当前运算符比栈顶元素运算符优先级高则返回true,否则返回false151 */

152 private boolean comparePri(charsymbol) {153 if (symbolStack.empty()) { //空栈返回ture

154 return true;155 }156

157 //符号优先级说明(从高到低):158 //第1级: (159 //第2级: * /160 //第3级: + -161 //第4级: )

162

163 char top = (char) symbolStack.peek(); //查看堆栈顶部的对象,注意不是出栈

164 if (top == '(') {165 return true;166 }167 //比较优先级

168 switch(symbol) {169 case '(': //优先级最高

170 return true;171 case '*': {172 if (top == '+' || top == '-') //优先级比+和-高

173 return true;174 else

175 return false;176 }177 case '/': {178 if (top == '+' || top == '-') //优先级比+和-高

179 return true;180 else

181 return false;182 }183 case '+':184 return false;185 case '-':186 return false;187 case ')': //优先级最低

188 return false;189 case '=': //结束符

190 return false;191 default:192 break;193 }194 return true;195 }196

197 //测试

198 public static voidmain(String args[]) {199 String num = "10 + (2*16-20/5) + 7*2 "; //默认的算式200 //创建一个窗口

201 JFrame win = new JFrame("计算器");202 Container con =win.getContentPane();203 JPanel pa = newJPanel();204 pa.add(new JLabel("输入算式:")); //添加一个标签

205 final JTextField formulaText = new JTextField(num, 20); //算式输入框

206 pa.add(formulaText);207 pa.add(new JLabel("="));208 final JTextField resultText = new JTextField(8); //结果文本框

209 pa.add(resultText);210 con.add(pa);211

212 JButton bn = new JButton("计算"); //实例化按钮对象

213 con.add(bn, BorderLayout.EAST); //将按钮添加到右边

214 win.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //设置关闭窗口退出程序

215 win.pack(); //自动调整大小

216 win.setLocationRelativeTo(null); //设置窗口居中于屏幕

217 win.setVisible(true); //显示窗口218

219 //添加按钮点击事件

220 bn.addActionListener(newActionListener() {221 @Override222 public void actionPerformed(ActionEvent e) { //每当按钮点击时调用该方法

223 /*计算器操作*/

224 Calculator cal = newCalculator();225 String numStr = formulaText.getText(); //获得算式文本框中的文字

226 long result = cal.caculate(numStr); //计算算式的结果

227 numStr = cal.removeStrSpace(numStr); //去空格

228 formulaText.setText(numStr); //将去空格的算式放回算式文本框中

229 resultText.setText(result + ""); //在结果文本框中显示结果

230 }231 });232 }233 }234

运行结果:

384149dd937dbccf6f654a735738087c.png

优化支持浮点数计算:

import java.math.BigDecimal;

import java.util.Stack;

/**

* 算式计算

*/

public class FormulaUtil {

private int scale; // 进行除法出现无线循环小数时保留的精度

/** 数字栈:用于存储表达式中的各个数字 */

private Stack numberStack = null;

/** 符号栈:用于存储运算符和括号 */

private Stack symbolStack = null;

public FormulaUtil(int scale) {

super();

this.scale = scale;

}

public FormulaUtil() {

this(32);

}

/**

* 解析并计算四则运算表达式(含括号优先级),返回计算结果

*

* @param numStr

* 算术表达式(含括号)

*/

public BigDecimal caculate(String numStr) {

numStr = removeStrSpace(numStr); // 去除空格

// 如果算术表达式尾部没有‘=’号,则在尾部添加‘=’,表示结束符

if (numStr.length() > 1

&& !"=".equals(numStr.charAt(numStr.length() - 1) + "")) {

numStr += "=";

}

// 检查表达式是否合法

if (!isStandard(numStr)) {

System.err.println("错误:算术表达式有误!");

return null;

}

// 初始化栈

if (numberStack == null) {

numberStack = new Stack();

}

numberStack.clear();

if (symbolStack == null) {

symbolStack = new Stack();

}

symbolStack.clear();

// 用于缓存数字,因为数字可能是多位的

StringBuffer temp = new StringBuffer();

// 从表达式的第一个字符开始处理

for (int i = 0; i < numStr.length(); i++) {

char ch = numStr.charAt(i); // 获取一个字符

if (isNumber(ch)) { // 若当前字符是数字

temp.append(ch); // 加入到数字缓存中

} else { // 非数字的情况

String tempStr = temp.toString(); // 将数字缓存转为字符串

if (!tempStr.isEmpty()) {

// long num = Long.parseLong(tempStr); // 将数字字符串转为长整型数

BigDecimal num = new BigDecimal(tempStr);

numberStack.push(num); // 将数字压栈

temp = new StringBuffer(); // 重置数字缓存

}

// 判断运算符的优先级,若当前优先级低于栈顶的优先级,则先把计算前面计算出来

while (!comparePri(ch) && !symbolStack.empty()) {

BigDecimal b = numberStack.pop(); // 出栈,取出数字,后进先出

BigDecimal a = numberStack.pop();

// 取出运算符进行相应运算,并把结果压栈进行下一次运算

switch ((char) symbolStack.pop()) {

case '+':

numberStack.push(a.add(b));

break;

case '-':

numberStack.push(a.subtract(b));

break;

case '*':

numberStack.push(a.multiply(b));

break;

case '/':

try {

numberStack.push(a.divide(b));

} catch (java.lang.ArithmeticException e) {

// 进行除法出现无限循环小数时,就会抛异常,此处设置精度重新计算

numberStack.push(a.divide(b, this.scale,

BigDecimal.ROUND_HALF_EVEN));

}

break;

default:

break;

}

} // while循环结束

if (ch != '=') {

symbolStack.push(new Character(ch)); // 符号入栈

if (ch == ')') { // 去括号

symbolStack.pop();

symbolStack.pop();

}

}

}

} // for循环结束

return numberStack.pop(); // 返回计算结果

}

/**

* 去除字符串中的所有空格

*/

private String removeStrSpace(String str) {

return str != null ? str.replaceAll(" ", "") : "";

}

/**

* 检查算术表达式的基本合法性,符合返回true,否则false

*/

private boolean isStandard(String numStr) {

if (numStr == null || numStr.isEmpty()) // 表达式不能为空

return false;

Stack stack = new Stack(); // 用来保存括号,检查左右括号是否匹配

boolean b = false; // 用来标记'='符号是否存在多个

for (int i = 0; i < numStr.length(); i++) {

char n = numStr.charAt(i);

// 判断字符是否合法

if (!(isNumber(n) || "(".equals(n + "") || ")".equals(n + "")

|| "+".equals(n + "") || "-".equals(n + "")

|| "*".equals(n + "") || "/".equals(n + "") || "=".equals(n

+ ""))) {

return false;

}

// 将左括号压栈,用来给后面的右括号进行匹配

if ("(".equals(n + "")) {

stack.push(n);

}

if (")".equals(n + "")) { // 匹配括号

if (stack.isEmpty() || !"(".equals((char) stack.pop() + "")) // 括号是否匹配

return false;

}

// 检查是否有多个'='号

if ("=".equals(n + "")) {

if (b)

return false;

b = true;

}

}

// 可能会有缺少右括号的情况

if (!stack.isEmpty())

return false;

// 检查'='号是否不在末尾

if (!("=".equals(numStr.charAt(numStr.length() - 1) + "")))

return false;

return true;

}

/**

* 判断字符是否是0-9的数字

*/

private boolean isNumber(char num) {

if ((num >= '0' && num <= '9') || num == '.')

return true;

return false;

}

/**

* 比较优先级:如果当前运算符比栈顶元素运算符优先级高则返回true,否则返回false

*/

private boolean comparePri(char symbol) {

if (symbolStack.empty()) { // 空栈返回ture

return true;

}

// 符号优先级说明(从高到低):

// 第1级: (

// 第2级: * /

// 第3级: + -

// 第4级: )

char top = (char) symbolStack.peek(); // 查看堆栈顶部的对象,注意不是出栈

if (top == '(') {

return true;

}

// 比较优先级

switch (symbol) {

case '(': // 优先级最高

return true;

case '*': {

if (top == '+' || top == '-') // 优先级比+和-高

return true;

else

return false;

}

case '/': {

if (top == '+' || top == '-') // 优先级比+和-高

return true;

else

return false;

}

case '+':

return false;

case '-':

return false;

case ')': // 优先级最低

return false;

case '=': // 结束符

return false;

default:

break;

}

return true;

}

// 测试

public static void main(String args[]) {

String numStr = "10.000000000000000009 + (2*16-20/4) + 7*2.5 "; // 默认的算式

BigDecimal result = new FormulaUtil().caculate(numStr); // 计算算式的结果

System.out.println(numStr + "=");

System.out.println(result);

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值