2016012054+小學四則運算練習軟件項目報告
作業源代碼地址:https://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.githttps://git.coding.net/mal123/elementary_arithmetic.git
一、需求分析
1、需要實現的功能
·程序可接收一個輸入參數n,然後隨機產生n道加減乘除(分別使用符號+-*÷來表示)練習題,每個數字在 0 和 100 之間,運算符在3個到5個之間;
·每個練習題至少要包含2種運算符;同時,所出的練習題在運算過程中不得出現負數與非整數;
·練習題生成好後,將你的學號與生成的n道練習題及其對應的正確答案輸出到文件“result.txt”中,不要輸出額外信息,文件目錄與程序目錄一致。
·支持有括號的運算式,包括出題與求解正確答案。註意,算式中存在的括號必須大於2個,且不得超過運算符的個數。(附加)
·支持真分數的出題與運算(只需要涵蓋加減法),註意在實現本功能時,需支持運算時分數的自動化簡,且計算過程中與結果都須為真分數。(附加)
2、具體分析
項目的主要功能:
題目的具體要求:
面向用戶:小學生、老師
針對小學生對於四則運算的掌握情況以及老師所要達到鍛煉學生的目的,對於題目有如下要求:
二、功能設計
1、基本功能
·隨機產生運算符(個數為3-5個),且至少有2種運算符。
·隨機產生運算數(個數為運算符個數+1),且每個數字在0-100之間。
·計算題目:1.判斷優先級 2.判斷是否出現負數,小數,以及除數不能為0。
·根據用戶輸入的個數,產生相應的題目數量。(判斷輸入參數是否合法[int類型][1-1000之間])
·創建result.txt(在根目錄下),將生成的題目寫入result.txt中,並在第一行顯示自己學號。
·能夠在命令行進行測試。項目必須包含src文件夾,在src文件夾中必須包含名為Main.java文件,且Main.java中包含 public static void main(String[] args)
2、擴展功能
·隨機產生括號,算式中存在的括號必須大於2個,且不得超過運算符的個數。(確保不會出現無意義的括號)
·支持真分數的出題與運算(只需要涵蓋加減法),支持運算時分數的自動化簡,且計算過程中與結果都須為真分數。
三、設計實現
考慮到時間的問題,所以我只對基本功能的實現進行了設計。具體的設計如下:
用例圖:
\
isReasonable()方法的流程圖:
在完成基礎功能的基礎上,我對附加功能進行了設計,但由於之前實現方法的局限性,對於括號這一附加功能很難加進去,於是只對分數這一部分的運算進行了實現。
具體修改的如下:
用例圖:
四、算法詳解
1、生成題目:用switch語句隨機生成運算符,並利用random方法隨機生成合理數量的運算符和運算數。
2、解答題目:采用遞歸的算法,計算最大公因數,最小公倍數,利用list,if-else語句循環判斷運算的優先級,和計算的合理性並進行計算。
五、測試運行
測試過程:
結果顯示:
修改之後的結果顯示:
六、代碼展示
CreatFile類:
1 import java.io.*; 2 3 /** 4 * 創建TXT文件,寫入數據 5 */ 6 public class CreatFile { 7 8 public void creatFile(int num) { 9 try { 10 File file = new File("../result.txt");//相對路徑 11 if (file.exists()) { 12 file.delete(); 13 } 14 if (file.createNewFile()) { 15 FileOutputStream fileout = new FileOutputStream(file); 16 fileout.write("2016012054".getBytes());//在第一行寫入學號 17 fileout.write("\r\n".getBytes());//換行 18 CheckAlgorithm checkAlgorithm = new CheckAlgorithm(); 19 CheckFraction checkFraction =new CheckFraction(); 20 //生成相應數量的題目,並寫入 21 for (int i = num; i > 0; i--) { 22 String str = null; 23 if(i % 3 == 0){ 24 str = checkFraction.calculate();//分數類題目 25 }else { 26 str = checkAlgorithm.isReasonable();//整數類題目 27 } 28 byte[] b = str.getBytes(); 29 fileout.write(b); 30 fileout.write("\r\n".getBytes()); 31 } 32 fileout.close(); 33 } 34 35 System.out.println("result.text文件創建成功!"); 36 } catch (FileNotFoundException e) { 37 e.printStackTrace(); 38 } catch (IOException e) { 39 e.printStackTrace(); 40 } 41 } 42 }
CheckAlgorithm類
1 import java.util.ArrayList; 2 import java.util.List; 3 4 /** 5 * 判斷運算是否合理並計算結果 6 */ 7 public class CheckAlgorithm { 8 9 public String isReasonable() { 10 String str = ""; 11 boolean flag = true; 12 int result = 0; 13 List<Character> charList = new ArrayList<>(); 14 List<Integer> numList = new ArrayList<>(); 15 List<Character> charList1 = new ArrayList<>(); 16 List<Integer> numList1 = new ArrayList<>(); 17 //循環直到生成正確的題目位置 18 while (flag) { 19 result = 0; 20 charList1.clear(); 21 numList1.clear(); 22 charList.clear(); 23 numList.clear(); 24 RandomUtil creatRandom = new RandomUtil(); 25 charList = creatRandom.isCharacterSame(); 26 numList = creatRandom.createRandomNum(); 27 charList1.addAll(charList); 28 numList1.addAll(numList); 29 //循環計算每一步結果並判斷是否合理 30 for (int i = charList.size() - 1; i >= 0; i--) { 31 // 有兩個及以上運算符時 32 if (i > 0) { 33 //‘+’後面為同級運算時 34 if (charList.get(i) == ‘+‘ && ((charList.get(i - 1) == ‘+‘) || (charList.get(i - 1) == ‘-‘))) { 35 result = numList.get(i + 1) + numList.get(i); 36 charList.remove(i); 37 numList.remove(i + 1); 38 numList.set(i, result); 39 continue; 40 } 41 //‘-’後面為同級運算時 42 if (charList.get(i) == ‘-‘ && ((charList.get(i - 1) == ‘+‘) || (charList.get(i - 1) == ‘-‘))) { 43 result = numList.get(i + 1) - numList.get(i); 44 if (result <= 0) { 45 break; 46 } else { 47 charList.remove(i); 48 numList.remove(i + 1); 49 numList.set(i, result); 50 continue; 51 } 52 } 53 //‘+’或‘-’後面為優先級更高的運算時 54 if (((charList.get(i) == ‘+‘) || (charList.get(i) == ‘-‘)) && charList.get(i - 1) == ‘*‘) { 55 result = numList.get(i) * numList.get(i - 1); 56 57 char tempChar = charList.get(i); 58 charList.remove(i); 59 charList.remove(i - 1); 60 charList.add(tempChar); 61 62 int tempNum = numList.get(i + 1); 63 numList.remove(i + 1); 64 numList.remove(i); 65 numList.set(i - 1, result); 66 numList.add(tempNum); 67 continue; 68 } 69 70 if (((charList.get(i) == ‘+‘) || (charList.get(i) == ‘-‘)) && charList.get(i - 1) == ‘÷‘) { 71 if (numList.get(i - 1) != 0) { 72 result = numList.get(i) / numList.get(i - 1); 73 74 if (numList.get(i) % numList.get(i - 1) != 0) { 75 break; 76 } else { 77 char tempChar = charList.get(i); 78 charList.remove(i); 79 charList.remove(i - 1); 80 charList.add(tempChar); 81 82 int tempNum = numList.get(i + 1); 83 numList.remove(i + 1); 84 numList.remove(i); 85 numList.set(i - 1, result); 86 numList.add(tempNum); 87 continue; 88 } 89 } else { 90 break; 91 } 92 } 93 } 94 // 只有一個運算符時 95 //乘法運算 96 if (charList.get(i) == ‘*‘ || (i == 0 && charList.get(i) == ‘*‘)) { 97 result = numList.get(i + 1) * numList.get(i); 98 charList.remove(i); 99 numList.remove(i + 1); 100 numList.set(i, result); 101 if (i == 0) { 102 flag = false; 103 } 104 continue; 105 } 106 //除法運算 107 if (charList.get(i) == ‘÷‘ || (i == 0 && charList.get(i) == ‘÷‘)) { 108 if (numList.get(i) != 0) { 109 result = numList.get(i + 1) / numList.get(i); 110 if (numList.get(i + 1) % numList.get(i) == 0) { 111 charList.remove(i); 112 numList.remove(i + 1); 113 numList.set(i, result); 114 if (i == 0) { 115 flag = false; 116 } 117 continue; 118 } else { 119 break; 120 } 121 } else { 122 break; 123 } 124 } 125 126 //加減法 127 if (i == 0) { 128 if (charList.get(i) == ‘+‘) { 129 result = numList.get(i + 1) + numList.get(i); 130 flag = false; 131 continue; 132 } 133 if (charList.get(i) == ‘-‘) { 134 result = numList.get(i + 1) - numList.get(i); 135 if (result < 0) { 136 break; 137 } 138 flag = false; 139 continue; 140 } 141 142 } 143 } 144 } 145 //輸出題目 146 for (int j = numList1.size() - 1; j >= 0; j--) { 147 if (j > 0) { 148 str += numList1.get(j); 149 str += charList1.get(j - 1); 150 } else { 151 str += numList1.get(j); 152 } 153 } 154 str += "=" + result; 155 return str; 156 } 157 }
OperationOfFra類
1 public class OperationOfFra { 2 3 //最大公因數 4 public int gcd(int a, int b) { 5 6 return a % b == 0 ? b : gcd(b, a % b); 7 } 8 9 // 最小公倍數 10 public int lcm(int n1, int n2) { 11 return n1 * n2 / gcd(n1, n2); 12 } 13 14 15 }
七、總結
在此次項目過程中,由於前期的設計不夠合理,導致在代碼編寫階段遇到了很多問題,只能一步一步debug,查找代碼的紕漏,給自己造成了很大的麻煩。其次是這次項目當中涉及到一些我沒有掌握的知識,例如如何向文件中寫入數據,Main方法怎麽在命令行獲取參數等。在實現過程中,我意識到了很多自己的不足之處,也讓我收獲了許多新的知識。
為了使代碼更加簡潔,我將隨機生成運算符和運算數、判斷題目合理性、創建TXT文件並寫入這些功能獨立成一個模塊,這樣在主方法中只需要調用相應的方法就可以,而不需要知道具體代碼的實現過程。
關於項目的設計,根據用戶需求,我首先想到的是如何生成一道正確的四則運算,這樣就可以利用循環,實現相應數量的題目。這其中,遇到最大的問題就是如何實現運算符優先級的判斷,我想到的解決方案是利用List,進行循環判斷,實現前兩個運算符的判斷,然後不斷循環,直到計算出結果。後來我也有看其他同學的博客,看到他們用調度場算法,也意識到自己算法的弊端,由於時間原因,我還是采用了之前設計的方法,完成了作業。以後的學習中,也會吸取這次的經驗,以最優化的方案完成作業。
八、PSP展示
PSP2.1 |
任務內容 |
計劃共完成需要的時間(min) |
實際完成需要的時間(min) |
Planning |
計劃 |
1*60 |
1*60 |
· Estimate |
· 估計這個任務需要多少時間,並規劃大致工作步驟 |
1*60 |
1*60 |
Development |
開發 |
21*60 |
21*60 |
· Analysis |
· 需求分析 (包括學習新技術) |
4*60 |
4*60 |
· Design Spec |
· 生成設計文檔 |
20 |
20 |
· Design Review |
· 設計復審 (和同事審核設計文檔) |
10 |
10 |
· Coding Standard |
· 代碼規範 (為目前的開發制定合適的規範) |
30 |
30 |
· Design |
· 具體設計 |
1*60 |
1*60 |
· Coding |
· 具體編碼 |
11*60 |
11*60 |
· Code Review |
· 代碼復審 |
1*60 |
1*60 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
2*60 |
2*60 |
Reporting |
報告 |
6*60 |
6*60 |
· Test Report |
· 測試報告 |
30 |
30 |
· Size Measurement |
· 計算工作量 |
30 |
30 |
· Postmortem & Process Improvement Plan |
· 事後總結, 並提出過程改進計劃 |
5*60 |
5*60 |
2016012054+小學四則運算練習軟件項目報告