JavaGUI实现科学计算器
JavaGUI實現科學計算器
一、設計思想
界面及布局
利用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 30log.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);// 將按鈕添加到CENTERadd(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 {@Overridepublic 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();} }沒有進行錯誤的一些處理,有什么問題隨時歡迎評論。
總結
以上是生活随笔為你收集整理的JavaGUI实现科学计算器的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 网件rax40可以刷梅林_美国网件发布全
- 下一篇: opencv rect画旋转矩形_在op