赞
踩
界面及布局
利用Java中awt、swing包里的工具对计算器布局设计(为了使运算可控,所以将文本区只能设为从Button输入)
给每个Button加监听器
对于数字和运算符Button,让其在文本行中显示算术表达式
LogClear:清理历史记录
LogTextEnable:对历史记录能否操作Button
BackSpace、C:BackSpace清除文本行中最后一个字符,C清除所有字符。
=:对文本行中算术表达式进行计算并显示结果,将结果显示到历史记录中。
核心算法(自己想的算法解决问题,可能存在致命性错误)
对字符串表达式进行计算
设计思想:
先不考虑()、e、π
将算术表达式拆分为A+B-C
形式,A、B、C中含有比 + - 更高级的运算符
对A、B、C进行判断,看其是否含有更高级的运算符,若没有,则直接进行加减运算。若有,则进行对更高级运算符的处理,看步骤4,然后进行加减运算处理。END
将A中表达式进行拆分为a*b/c
形式,a、b、c中含有更高级运算符
对a、b、c进行判断,看其是否含有更高级的运算符,若没有,则直接进行乘除
运算。若有,则进行对更高级运算符的处理,看步骤5,然后进行乘除
运算处理。
将a中表达式进行拆分为x^y^z
(x的y*z次方或x的y次方的z次方,结果一样)形式,x、y、z中含有更高级运算符
对x、y、z进行判断,看其是否含有更高级的运算符,若没有,则直接进行幂
运算。若有,则进行对更高级运算符的处理,看步骤6,然后进行幂
运算处理。
到了此步x、y、z中就只包含了一个数字,对其操作有开方(其与幂运算等级不影响结果)、cos、sin、tan、!(阶乘),若有运算级歧义可用()
处理。
对x、y、z扫描取出数字,先进行阶乘判断若有阶乘符号则对数字进行阶乘运算,因为阶乘只能对整数操作,其他运算有特别大几率产生小数。再进行开方判断……
对()、e、π
处理(若运算级优先级有问题可以用括号提升优先级)
e、π其特点是只有一个字符可对表达式进行一次扫描,若有则调用Math包中Math.E、Math.PI对其替换
()
:对表达式进行一次遍历,利用List<StringBuffer>
对表达式进行处理,若扫描到(
则将下一个扫描的字符存储到下一个StringBuffer中,若扫描到)
则对这一个StringBuffer进行计算,计算方法为1~6
项目文件结构:
CalculatorFrame.java文件:对页面的设置
package com.zhao.calc.frame; import java.awt.BorderLayout; import javax.swing.JFrame; public class CalculatorFrame extends JFrame { /** * */ private static final long serialVersionUID = 1L; public CalculatorFrame() { setTitle("计算器"); // 设置窗口标题 setSize(1200, 600); // 设置窗口大小 add(new CalculatorPanel(), BorderLayout.CENTER); setVisible(true); //设置可见 } }
CalculatorPanel.java文件:对面板布局的管理
package com.zhao.calc.frame; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Font; import java.awt.GridLayout; import java.awt.TextArea; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.JTextField; import com.zhao.calc.util.CalculatorMathUtils; public class CalculatorPanel extends JPanel { private static final long serialVersionUID = 1L; private JPanel panel = null; private Font font = null; private JTextField display = null; private TextArea log = null; private String nowButton = null; private boolean logEnable = true; // log 使能 判别 public CalculatorPanel() { setLayout(new BorderLayout()); // 设置为网格布局 font = new Font("宋体", 4, 30); // 设置字体 // 添加文本框 display = new JTextField(""); // 默认置为空 display.setEnabled(false); // display设置为不能编辑 display.setFont(font); add(display, BorderLayout.NORTH); // 把文本框加在上面north里 // 添加日志 log = new TextArea(500, 30); // 大小为rows 500 columns 30 log.setFont(new Font("宋体", 4, 20)); log.setForeground(Color.BLUE); // 字体颜色 enable为true 可见 log.setEnabled(false); log.setText("历史记录:\n"); add(log, BorderLayout.EAST); // 把文本框加在上面east里 // 监听操作按钮 ActionListener command = new CommandAction(); // panel是中间按钮的布局,放到布局管理器的center里 panel = new JPanel(); panel.setLayout(new GridLayout(8, 4)); // panel为网格布局 8行 4列 // 设置按钮 addButton("LogClear", command); addButton("LogTextEnable", command); addButton("BackSpace", command); addButton("C", command); addButton("e", command); addButton("π", command); addButton("tan", command); addButton("!", command); addButton("√", command); addButton("^", command); addButton("cos", command); addButton("sin", command); addButton("(", command); addButton(")", command); addButton("log", command); addButton("ln", command); addButton("7", command); addButton("8", command); addButton("9", command); addButton("+", command); addButton("4", command); addButton("5", command); addButton("6", command); addButton("-", command); addButton("1", command); addButton("2", command); addButton("3", command); addButton("*", command); addButton(".", command); addButton("0", command); addButton("=", command); addButton("/", command); // 将按钮添加到CENTER add(panel, BorderLayout.CENTER); } // 添加button 添加事件 public void addButton(String label, ActionListener listener) { JButton button = new JButton(label); button.setFont(font); // 设置按钮字体 button.addActionListener(listener); // 添加监听器 panel.add(button); // 将按钮添加到panel中 } // 单击按钮执行命令的监听器 class CommandAction implements ActionListener { @Override public void actionPerformed(ActionEvent event) { // 获得产生事件的按钮名称 nowButton = event.getActionCommand(); // 将按钮的名称打印到display中 if (nowButton != "BackSpace" && nowButton != "=" && nowButton != "LogClear" && nowButton != "LogTextEnable") { // 如果是BackSace = LogClear LogTextEnable就不打印这个了 display.setText(display.getText() + nowButton); } if (nowButton.equals("=")) { // 如果是等于号,就计算结果 并打印日志 log.append(display.getText() + "\n= " + CalculatorMathUtils.calcString(display.getText()) + "\n"); display.setText(CalculatorMathUtils.calcString(display.getText())); } if (nowButton.equals("BackSpace")) { // 回退一个字符 StringBuffer sb = new StringBuffer(display.getText()); if (sb.length() != 0) { display.setText(sb.substring(0, sb.length() - 1)); } } if (nowButton.equals("C")) { // 清空 display.setText(""); } if (nowButton.equals("LogClear")) { // 清空历史记录 log.setText("历史记录:\n"); } if (nowButton.equals("LogTextEnable")) { // 设置历史记录 使能 log.setEnabled(logEnable); logEnable = !logEnable; } } } }
CalculatorMathUtils.java文件:对算术表达式的处理的工具类
package com.zhao.calc.util; import java.util.ArrayList; import java.util.List; public class CalculatorMathUtils { // 对算术表达式进行计算 public static String calcString(String str) { // 对 e π 进行替换 StringBuffer sb = new StringBuffer(); for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == 'e') { sb.append(Math.E); continue; } if (str.charAt(i) == 'π') { sb.append(Math.PI); continue; } sb.append(str.charAt(i)); } str = sb.toString(); // 对 ( ) 进行处理 List<StringBuffer> list = new ArrayList<StringBuffer>(); int level = 0; list.add(new StringBuffer()); for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '(') { list.add(new StringBuffer()); level++; continue; } if (str.charAt(i) == ')') { list.get(level - 1).append(String.valueOf(calcString(list.get(level).toString()))); list.remove(level); level--; continue; } list.get(level).append(str.charAt(i)); } return calcLevel1(list.get(level).toString()); } /* * 第一层级 + - 运算 */ private static String calcLevel1(String str) { /* 对负号进行处理 * 对 1+-5 1--5进行计算 * 第四层级 cos- -> cos sin- -> -sin * log- ln- √- 报错 */ str = str.replace("--", "+"); str = str.replace("+-", "-"); str = str.replace("*+", "*"); str = str.replace("/+", "/"); str = str.replace("^+", "^"); if (str.contains("cos-")) { str = str.replace("cos-", "cos"); } if (str.contains("sin-")) { str = str.replace("sin-", "-sin"); } if (str.contains("tan-")) { str = str.replace("tan-", "-tan"); } if (str.contains("log-") || str.contains("ln-") || str.contains("√-")) { return "error:log- ln- √-"; } str = str.replace("--", "+"); str = str.replace("+-", "-"); StringBuffer sb = new StringBuffer(str); int commandCount = 0;// 符号数量 int j = 0;// 计数器 // 计算有+ -个运算符,就有n+1个数字 for (j = 0; j < sb.length() - 1; j++) { // 对第一个数符号进行处理 if (j == 0 && sb.charAt(j) == '-') { continue; } if (j == 0 && sb.charAt(j) == '+') { continue; } String flag = "" + str.charAt(j) + str.charAt(j + 1); if (flag.equals("*-") || flag.equals("/-") || flag.equals("^-")) { j++; continue; } if (sb.charAt(j) == '+' || sb.charAt(j) == '-') commandCount++; } // 初始化符号数组 char[] command = new char[commandCount]; // 初始化数字数组(用字符串表示) String[] num = new String[commandCount + 1]; for (j = 0; j < num.length; j++) { num[j] = ""; } // 遍历一遍,吧每个数字存进数字数组,每个符号存进符号数组 int k = 0; for (j = 0; j < sb.length(); j++) { // 对第一个数是否为负数进行处理 if (j == 0 && sb.charAt(j) == '-') { num[k] += sb.charAt(j); continue; } if (j == 0 && sb.charAt(j) == '+') { continue; } // 对 *- /- ^- 进行处理 if (j + 1 < sb.length()) { String flag = "" + sb.charAt(j) + sb.charAt(j + 1); if (flag.equals("*-") || flag.equals("/-") || flag.equals("^-")) { num[k] += flag; j++; continue; } } //对 + - 运算符进行保存 if (sb.charAt(j) == '+' || sb.charAt(j) == '-') { command[k] = sb.charAt(j); k++; continue; } // 将数字及更高级运算保存在num[k]中 num[k] += sb.charAt(j); } // 当num[i]中有更高级运算时对num[i]传入到calcLevel2(num[i])方法中进行解决 for (int i = 0; i < num.length; i++) { if (num[i].contains("*") || num[i].contains("/") || num[i].contains("^") || num[i].contains("cos") || num[i].contains("sin") || num[i].contains("tan")|| num[i].contains("log") || num[i].contains("ln") || num[i].contains("!") || num[i].contains("√")) { num[i] = calcLevel2(num[i]); } } // 如果只包含一个数 返回这个数的值 if (num.length == 1) { return num[0]; } double result = 0; for (int i = 0; i < commandCount; i++) { // 取前两个数,和第一个操作符,运算 double num1 = 0; double num2 = 0; try { num1 = Double.parseDouble(num[i]); num2 = Double.parseDouble(num[i + 1]); } catch (NumberFormatException e) { e.printStackTrace(); } //取+ - 运算符进行运算 char cc = command[i]; if (cc == '+') { result = num1 + num2; } else if (cc == '-') { result = num1 - num2; } num[i + 1] = String.valueOf(result); } return String.valueOf(result); } /* * 第二层级 * / 运算 */ private static String calcLevel2(String str) { StringBuffer sb = new StringBuffer(str); int commandCount = 0;// 符号数量 int j = 0;// 计数器 // 计算有多少个运算符,就有n+1个数字 for (j = 0; j < sb.length(); j++) { if (sb.charAt(j) == '*' || sb.charAt(j) == '/') commandCount++; } // 初始化符号数组 char[] command = new char[commandCount]; // 初始化数字数组(用字符串表示) String[] num = new String[commandCount + 1]; for (j = 0; j < num.length; j++) { num[j] = ""; } // 遍历一遍,吧每个数字存进数字数组,* /符号存进符号数组 int k = 0; for (j = 0; j < sb.length(); j++) { if (sb.charAt(j) == '*' || sb.charAt(j) == '/') { command[k] = sb.charAt(j); k++; continue; } // 将数字及更高级运算保存在num[k]中 num[k] += sb.charAt(j); } // 当num[i]中有更高级运算时对num[i]传入到calcLevel3(num[i])方法中进行解决 for (int i = 0; i < num.length; i++) { if (num[i].contains("^") || num[i].contains("cos") || num[i].contains("sin") || num[i].contains("tan")|| num[i].contains("log") || num[i].contains("ln") || num[i].contains("!") || num[i].contains("√")) { num[i] = calcLevel3(num[i]); } } // 如果只包含一个数 返回这个数的值 if (num.length == 1) { return num[0]; } double result = 0; for (int i = 0; i < commandCount; i++) { // 取前两个数,和第一个操作符,运算 double num1 = 0; double num2 = 0; try { num1 = Double.parseDouble(num[i]); num2 = Double.parseDouble(num[i + 1]); } catch (NumberFormatException e) { e.printStackTrace(); } char cc = command[i]; if (cc == '*') { result = num1 * num2; } else if (cc == '/') { result = num1 / num2; } num[i + 1] = String.valueOf(result); } return String.valueOf(result); } /* * 第三层级 ^ 运算 */ private static String calcLevel3(String str) { StringBuffer sb = new StringBuffer(str); int commandCount = 0;// 符号数量 int j = 0;// 计数器 // 计算有多少个运算符,就有n+1个数字 for (j = 0; j < sb.length(); j++) { if (sb.charAt(j) == '^') commandCount++; } // 初始化数字数组(用字符串表示) String[] num = new String[commandCount + 1]; for (j = 0; j < num.length; j++) { num[j] = ""; } // 遍历一遍,吧每个数字存进数字数组,^符号存进符号数组 int k = 0; for (j = 0; j < sb.length(); j++) { if (sb.charAt(j) == '^') { k++; continue; } num[k] += sb.charAt(j); } for (int i = 0; i < num.length; i++) { if (num[i].contains("cos") || num[i].contains("sin")|| num[i].contains("tan") || num[i].contains("log") || num[i].contains("ln") || num[i].contains("!") || num[i].contains("√")) { num[i] = calcLevel4(num[i]); } } // 如果只包含一个数 返回这个数的值 if (num.length == 1) { return num[0]; } double result = 1; for (int i = 1; i < num.length; i++) { result *= Double.parseDouble(num[i]); } result = Math.pow(Double.parseDouble(num[0]), result); return String.valueOf(result); } /* * 第四层级 cos sin ! √ 运算 * 若 嵌套使用建议采用 () */ private static String calcLevel4(String str) { StringBuffer sb = new StringBuffer(str); String num = ""; for (int i = 0; i < sb.length(); i++) { if (sb.charAt(i) <= '9' && sb.charAt(i) >= '0' || sb.charAt(i) == '.') { num += sb.charAt(i); } } if (str.contains("!")) { try { num = String.valueOf(factorial(Integer.parseInt(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("√")) { try { num = String.valueOf(Math.sqrt(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("cos")) { try { num = String.valueOf(Math.cos(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("sin")) { try { num = String.valueOf(Math.sin(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("tan")) { try { num = String.valueOf(Math.tan(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("log")) { try { num = String.valueOf(Math.log10(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } if (str.contains("ln")) { try { num = String.valueOf(Math.log(Double.parseDouble(num))); } catch (NumberFormatException e) { e.printStackTrace(); } } return num; } // 求n的阶乘 n! public static int factorial(int n) { if (n == 0) { return 1; } int num = n; for (int i = n; i > 1; i--) { num *= (i - 1); } return num; } }
testMathUtils.java文件:对算术表达式的测试。(这个就不发了。嘿嘿!)
Main.java文件:运行主函数的类
package com.zhao.calc.test;
import com.zhao.calc.frame.CalculatorFrame;
public class Main {
public static void main(String[] args) {
new CalculatorFrame();
}
}
没有进行错误的一些处理,有什么问题随时欢迎评论。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。