JavaGUI实现科学计算器
JavaGUI實(shí)現(xiàn)科學(xué)計(jì)算器
一、設(shè)計(jì)思想
界面及布局
利用Java中awt、swing包里的工具對(duì)計(jì)算器布局設(shè)計(jì)(為了使運(yùn)算可控,所以將文本區(qū)只能設(shè)為從Button輸入)
給每個(gè)Button加監(jiān)聽器
對(duì)于數(shù)字和運(yùn)算符Button,讓其在文本行中顯示算術(shù)表達(dá)式
LogClear:清理歷史記錄
LogTextEnable:對(duì)歷史記錄能否操作Button
BackSpace、C:BackSpace清除文本行中最后一個(gè)字符,C清除所有字符。
=:對(duì)文本行中算術(shù)表達(dá)式進(jìn)行計(jì)算并顯示結(jié)果,將結(jié)果顯示到歷史記錄中。
核心算法(自己想的算法解決問題,可能存在致命性錯(cuò)誤)
對(duì)字符串表達(dá)式進(jìn)行計(jì)算
設(shè)計(jì)思想:
先不考慮()、e、π
將算術(shù)表達(dá)式拆分為A+B-C形式,A、B、C中含有比 + - 更高級(jí)的運(yùn)算符
對(duì)A、B、C進(jìn)行判斷,看其是否含有更高級(jí)的運(yùn)算符,若沒有,則直接進(jìn)行加減運(yùn)算。若有,則進(jìn)行對(duì)更高級(jí)運(yùn)算符的處理,看步驟4,然后進(jìn)行加減運(yùn)算處理。END
將A中表達(dá)式進(jìn)行拆分為a*b/c形式,a、b、c中含有更高級(jí)運(yùn)算符
對(duì)a、b、c進(jìn)行判斷,看其是否含有更高級(jí)的運(yùn)算符,若沒有,則直接進(jìn)行乘除運(yùn)算。若有,則進(jìn)行對(duì)更高級(jí)運(yùn)算符的處理,看步驟5,然后進(jìn)行乘除運(yùn)算處理。
將a中表達(dá)式進(jìn)行拆分為x^y^z(x的y*z次方或x的y次方的z次方,結(jié)果一樣)形式,x、y、z中含有更高級(jí)運(yùn)算符
對(duì)x、y、z進(jìn)行判斷,看其是否含有更高級(jí)的運(yùn)算符,若沒有,則直接進(jìn)行冪運(yùn)算。若有,則進(jìn)行對(duì)更高級(jí)運(yùn)算符的處理,看步驟6,然后進(jìn)行冪運(yùn)算處理。
到了此步x、y、z中就只包含了一個(gè)數(shù)字,對(duì)其操作有開方(其與冪運(yùn)算等級(jí)不影響結(jié)果)、cos、sin、tan、!(階乘),若有運(yùn)算級(jí)歧義可用()處理。
對(duì)x、y、z掃描取出數(shù)字,先進(jìn)行階乘判斷若有階乘符號(hào)則對(duì)數(shù)字進(jìn)行階乘運(yùn)算,因?yàn)殡A乘只能對(duì)整數(shù)操作,其他運(yùn)算有特別大幾率產(chǎn)生小數(shù)。再進(jìn)行開方判斷……
對(duì)()、e、π處理(若運(yùn)算級(jí)優(yōu)先級(jí)有問題可以用括號(hào)提升優(yōu)先級(jí))
e、π其特點(diǎn)是只有一個(gè)字符可對(duì)表達(dá)式進(jìn)行一次掃描,若有則調(diào)用Math包中Math.E、Math.PI對(duì)其替換
():對(duì)表達(dá)式進(jìn)行一次遍歷,利用List<StringBuffer>對(duì)表達(dá)式進(jìn)行處理,若掃描到(則將下一個(gè)掃描的字符存儲(chǔ)到下一個(gè)StringBuffer中,若掃描到)則對(duì)這一個(gè)StringBuffer進(jìn)行計(jì)算,計(jì)算方法為1~6
二、算法實(shí)現(xiàn)
項(xiàng)目文件結(jié)構(gòu):
CalculatorFrame.java文件:對(duì)頁面的設(shè)置
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("計(jì)算器"); // 設(shè)置窗口標(biāo)題setSize(1200, 600); // 設(shè)置窗口大小add(new CalculatorPanel(), BorderLayout.CENTER);setVisible(true); //設(shè)置可見}}CalculatorPanel.java文件:對(duì)面板布局的管理
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()); // 設(shè)置為網(wǎng)格布局font = new Font("宋體", 4, 30); // 設(shè)置字體// 添加文本框display = new JTextField(""); // 默認(rèn)置為空display.setEnabled(false); // display設(shè)置為不能編輯display.setFont(font);add(display, BorderLayout.NORTH); // 把文本框加在上面north里// 添加日志log = new TextArea(500, 30); // 大小為rows 500 columns 30log.setFont(new Font("宋體", 4, 20));log.setForeground(Color.BLUE); // 字體顏色 enable為true 可見log.setEnabled(false);log.setText("歷史記錄:\n");add(log, BorderLayout.EAST); // 把文本框加在上面east里// 監(jiān)聽操作按鈕ActionListener command = new CommandAction();// panel是中間按鈕的布局,放到布局管理器的center里panel = new JPanel();panel.setLayout(new GridLayout(8, 4)); // panel為網(wǎng)格布局 8行 4列// 設(shè)置按鈕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);// 將按鈕添加到CENTERadd(panel, BorderLayout.CENTER);}// 添加button 添加事件public void addButton(String label, ActionListener listener) {JButton button = new JButton(label);button.setFont(font); // 設(shè)置按鈕字體button.addActionListener(listener); // 添加監(jiān)聽器panel.add(button); // 將按鈕添加到panel中}// 單擊按鈕執(zhí)行命令的監(jiān)聽器class CommandAction implements ActionListener {@Overridepublic void actionPerformed(ActionEvent event) {// 獲得產(chǎn)生事件的按鈕名稱nowButton = event.getActionCommand();// 將按鈕的名稱打印到display中if (nowButton != "BackSpace" && nowButton != "=" && nowButton != "LogClear"&& nowButton != "LogTextEnable") {// 如果是BackSace = LogClear LogTextEnable就不打印這個(gè)了display.setText(display.getText() + nowButton);}if (nowButton.equals("=")) {// 如果是等于號(hào),就計(jì)算結(jié)果 并打印日志log.append(display.getText() + "\n= " + CalculatorMathUtils.calcString(display.getText()) + "\n");display.setText(CalculatorMathUtils.calcString(display.getText()));}if (nowButton.equals("BackSpace")) {// 回退一個(gè)字符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")) {// 設(shè)置歷史記錄 使能log.setEnabled(logEnable);logEnable = !logEnable;}}} }CalculatorMathUtils.java文件:對(duì)算術(shù)表達(dá)式的處理的工具類
package com.zhao.calc.util;import java.util.ArrayList; import java.util.List;public class CalculatorMathUtils {// 對(duì)算術(shù)表達(dá)式進(jìn)行計(jì)算public static String calcString(String str) {// 對(duì) e π 進(jìn)行替換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();// 對(duì) ( ) 進(jìn)行處理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());}/** 第一層級(jí) + - 運(yùn)算*/private static String calcLevel1(String str) {/* 對(duì)負(fù)號(hào)進(jìn)行處理 * 對(duì) 1+-5 1--5進(jìn)行計(jì)算 * 第四層級(jí) cos- -> cos sin- -> -sin * log- ln- √- 報(bào)錯(cuò)*/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;// 符號(hào)數(shù)量int j = 0;// 計(jì)數(shù)器// 計(jì)算有+ -個(gè)運(yùn)算符,就有n+1個(gè)數(shù)字for (j = 0; j < sb.length() - 1; j++) {// 對(duì)第一個(gè)數(shù)符號(hào)進(jìn)行處理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++;}// 初始化符號(hào)數(shù)組char[] command = new char[commandCount];// 初始化數(shù)字?jǐn)?shù)組(用字符串表示)String[] num = new String[commandCount + 1];for (j = 0; j < num.length; j++) {num[j] = "";}// 遍歷一遍,吧每個(gè)數(shù)字存進(jìn)數(shù)字?jǐn)?shù)組,每個(gè)符號(hào)存進(jìn)符號(hào)數(shù)組int k = 0;for (j = 0; j < sb.length(); j++) {// 對(duì)第一個(gè)數(shù)是否為負(fù)數(shù)進(jìn)行處理if (j == 0 && sb.charAt(j) == '-') {num[k] += sb.charAt(j);continue;}if (j == 0 && sb.charAt(j) == '+') {continue;}// 對(duì) *- /- ^- 進(jìn)行處理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;}}//對(duì) + - 運(yùn)算符進(jìn)行保存if (sb.charAt(j) == '+' || sb.charAt(j) == '-') {command[k] = sb.charAt(j);k++;continue;}// 將數(shù)字及更高級(jí)運(yùn)算保存在num[k]中num[k] += sb.charAt(j);}// 當(dāng)num[i]中有更高級(jí)運(yùn)算時(shí)對(duì)num[i]傳入到calcLevel2(num[i])方法中進(jìn)行解決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]);}}// 如果只包含一個(gè)數(shù) 返回這個(gè)數(shù)的值if (num.length == 1) {return num[0];}double result = 0;for (int i = 0; i < commandCount; i++) {// 取前兩個(gè)數(shù),和第一個(gè)操作符,運(yùn)算double num1 = 0;double num2 = 0;try {num1 = Double.parseDouble(num[i]);num2 = Double.parseDouble(num[i + 1]);} catch (NumberFormatException e) {e.printStackTrace();}//取+ - 運(yùn)算符進(jìn)行運(yùn)算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);}/** 第二層級(jí) * / 運(yùn)算*/private static String calcLevel2(String str) {StringBuffer sb = new StringBuffer(str);int commandCount = 0;// 符號(hào)數(shù)量int j = 0;// 計(jì)數(shù)器// 計(jì)算有多少個(gè)運(yùn)算符,就有n+1個(gè)數(shù)字for (j = 0; j < sb.length(); j++) {if (sb.charAt(j) == '*' || sb.charAt(j) == '/')commandCount++;}// 初始化符號(hào)數(shù)組char[] command = new char[commandCount];// 初始化數(shù)字?jǐn)?shù)組(用字符串表示)String[] num = new String[commandCount + 1];for (j = 0; j < num.length; j++) {num[j] = "";}// 遍歷一遍,吧每個(gè)數(shù)字存進(jìn)數(shù)字?jǐn)?shù)組,* /符號(hào)存進(jìn)符號(hào)數(shù)組int k = 0;for (j = 0; j < sb.length(); j++) {if (sb.charAt(j) == '*' || sb.charAt(j) == '/') {command[k] = sb.charAt(j);k++;continue;}// 將數(shù)字及更高級(jí)運(yùn)算保存在num[k]中num[k] += sb.charAt(j);}// 當(dāng)num[i]中有更高級(jí)運(yùn)算時(shí)對(duì)num[i]傳入到calcLevel3(num[i])方法中進(jìn)行解決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]);}}// 如果只包含一個(gè)數(shù) 返回這個(gè)數(shù)的值if (num.length == 1) {return num[0];}double result = 0;for (int i = 0; i < commandCount; i++) {// 取前兩個(gè)數(shù),和第一個(gè)操作符,運(yùn)算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);}/** 第三層級(jí) ^ 運(yùn)算*/private static String calcLevel3(String str) {StringBuffer sb = new StringBuffer(str);int commandCount = 0;// 符號(hào)數(shù)量int j = 0;// 計(jì)數(shù)器// 計(jì)算有多少個(gè)運(yùn)算符,就有n+1個(gè)數(shù)字for (j = 0; j < sb.length(); j++) {if (sb.charAt(j) == '^')commandCount++;}// 初始化數(shù)字?jǐn)?shù)組(用字符串表示)String[] num = new String[commandCount + 1];for (j = 0; j < num.length; j++) {num[j] = "";}// 遍歷一遍,吧每個(gè)數(shù)字存進(jìn)數(shù)字?jǐn)?shù)組,^符號(hào)存進(jìn)符號(hào)數(shù)組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]);}}// 如果只包含一個(gè)數(shù) 返回這個(gè)數(shù)的值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);}/** 第四層級(jí) cos sin ! √ 運(yùn)算* 若 嵌套使用建議采用 () */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文件:對(duì)算術(shù)表達(dá)式的測(cè)試。(這個(gè)就不發(fā)了。嘿嘿!)
Main.java文件:運(yùn)行主函數(shù)的類
package com.zhao.calc.test;import com.zhao.calc.frame.CalculatorFrame;public class Main {public static void main(String[] args) {new CalculatorFrame();} }沒有進(jìn)行錯(cuò)誤的一些處理,有什么問題隨時(shí)歡迎評(píng)論。
總結(jié)
以上是生活随笔為你收集整理的JavaGUI实现科学计算器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网件rax40可以刷梅林_美国网件发布全
- 下一篇: Java Filter——敏感词汇过滤