一、項目Github地址
https://github.com/LilyFuEnLi/Arithmetic_SE
(注:附上coding.net項目網址:https://git.coding.net/LilyF/Software.git,coding.net與GitHub功能相同,coding.net的語言為中文,而GitHub是英文。)
二、項目報告
1、需求分析
(1)程序可接收一個輸入參數n,然后隨機產生n道加減乘除練習題,每個數字在 0 和 100 之間,運算符在3個到5個之間,即運算數字在4~6個之間。
(2)為了讓小學生得到充分鍛煉,每個練習題至少要包含2種運算符。同時,由於小學生沒有分數與負數的概念,你所出的練習題在運算過程中不得出現負數與非整數,比如不能出 3/5+2=2.6,2-5+10=7等算式。
(3)練習題生成好后,將自己的學號與生成的n道練習題及其對應的正確答案輸出到文件“result.txt”中,不要輸出額外信息,文件目錄與程序目錄一致。
(4)當程序接收的參數為5時,即產生5個運算式,以下為我試驗中輸出的文件,第一行為我的學號。
201571030108 (44*66)+(67-54)=2917 (43+54)-22*(37-37)=97 (74+35)*63+(17-17)=6867 (58+54)-(18+54)=50 (24+65)-(9+50)=30 |
(5)附加功能:支持有括號的運算式,包括出題與求解正確答案。由於隨機產生的運算數字為4~6個,所以算式中存在的括號設置為2個。
2、功能設計
(1)屏幕打印提示輸入需要產生的運算式個數number。
(2) 生成一個包含4~6個數字,3~5個運算符且包含兩個括號的字符串表達式。
(3)屏幕依次顯示number個運算式,要求學生解答,並顯示答題是否正確。
(5)計算出表達式的結果,並且運算過程中不能出現負數。
(4)統計學生答題情況,計算並顯示學生的正確率。
(5)最后將運算表達式和計算結果寫入result.txt文件,提示學生進行查詢並復習。
3、設計實現
目含有兩個java文件,分別是Main.java與Calculate_SE .java,Calculate_SE .java中包含calaulate_AE(產生隨機運算式)、transferToPostfix(中綴表達式轉化為逆波蘭式)、calculate(計算逆波蘭式)等方法,Main調用Calculate_SE中的各個方法完成項目,設計流程圖如圖1所示。
圖 1 設計流程圖
4、測試運行
運行Main.java文件,輸入產生運算式個數number為5,依次進行答題(如圖2所示),同時生成result.txt文件,如圖3所示,cmd運行文件run.bat文件截圖如圖4所示。
圖2 圖3
圖 4
5、核心代碼
(1)生成隨機運算式,調用方法計算結果

1 public void calaulate_AE(int number) { 2 int Right=0; 3 float R = 0; 4 int F=0; 5 while(F==0) 6 { 7 for(int i=0;i<number;i++) 8 { 9 CN[i]=(int)(Math.random()*2+4); 10 int Bracket=(int)(Math.random()*CN[i]-2); 11 for(int j=0;j<CN[i];j++) 12 { 13 N[i][j]=(int) (Math.random()*100+1); 14 } 15 for(int k=0;k<CN[i]-1;k++) 16 { 17 C[i][k]=Str[(int)(Math.random()*3)]; 18 } 19 for(int k=0;k<CN[i]-1;k++) 20 { 21 while(C[i][0]==C[i][1]) 22 C[i][1]=Str[(int)(Math.random()*3)]; 23 if(C[i][k]=='-' && (N[i][k]<N[i][k+1])) 24 { 25 int temp=0; 26 temp=N[i][k]; 27 N[i][k+1]=temp; 28 N[i][k]=temp; 29 } 30 if(C[i][k]=='/' && (N[i][k]%N[i][k+1]!=0)) 31 { 32 int temp=N[i][k]; 33 N[i][k] = N[i][k] <N[i][k+1]? N[i][k]: N[i][k+1]; 34 N[i][k+1] = temp > N[i][k+1]? temp: N[i][k+1]; 35 for(int num = N[i][k]; num >= 1; num--) 36 { 37 if(N[i][k] % num == 0 && N[i][k+1] % num == 0) 38 { 39 N[i][k+1]=num; 40 break; 41 } 42 } 43 } 44 } 45 String AE=new String(); 46 LinkedList<String> list=new LinkedList<>(); 47 list.add(String.valueOf('(')); 48 list.add(String.valueOf(N[i][0])); 49 list.add(String.valueOf(C[i][0])); 50 list.add(String.valueOf(N[i][1])); 51 list.add(String.valueOf(')')); 52 list.add(String.valueOf(C[i][1])); 53 AE+='('+String.valueOf(N[i][0])+String.valueOf(C[i][0])+String.valueOf(N[i][1])+')'+String.valueOf(C[i][1]); 54 for(int j=2;j<CN[i]-2;j++) 55 { 56 list.add(String.valueOf(N[i][j])); 57 list.add(String.valueOf(C[i][j])); 58 AE+=String.valueOf(N[i][j])+String.valueOf(C[i][j]); 59 } 60 list.add(String.valueOf('(')); 61 list.add(String.valueOf(N[i][CN[i]-2])); 62 list.add(String.valueOf(C[i][CN[i]-2])); 63 list.add(String.valueOf(N[i][CN[i]-1])); 64 list.add(String.valueOf(')')); 65 AE+='('+String.valueOf(N[i][CN[i]-2])+String.valueOf(C[i][CN[i]-2])+String.valueOf(N[i][CN[i]-1])+')'+'='; 66 String sum=transferToPostfix(list); 67 char fir =sum.charAt(0); 68 if(fir=='-') 69 F=0; 70 else 71 F=1; 72 System.out.print(AE); 73 String SUM=scanner.nextLine(); 74 if(SUM.equals(sum)) 75 { 76 System.out.print("回答真確,Very Good!(*^▽^*):\n"); 77 Right++; 78 } 79 else 80 System.out.print("回答錯誤,要加油哦!(*^▽^*):\n"); 81 float R1 = (float)Right; 82 float R2 = (float)number; 83 R=(float) (R1/R2*100.00); 84 AE+=sum; 85 Arithmetic.add(AE); 86 } 87 System.out.print("本次答題共計"+number+"道,回答正確"+Right+"道,正確率為"+R+"%.\n"); 88 } 89 }
(2)中綴表達式轉為后綴表達式

private static String transferToPostfix(LinkedList<String> list){ Iterator<String> it=list.iterator(); while (it.hasNext()) { String s = it.next(); if (isOperator(s)) { if (operators.isEmpty()) { operators.push(s); } else {//如果讀入的操作符為非")"且優先級比棧頂元素的優先級高或一樣,則將操作符壓入棧 if (priority(operators.peek())<=priority(s)&&!s.equals(")")) { operators.push(s); } else if(!s.equals(")")&&priority(operators.peek())>priority(s)) { while (operators.size()!=0&&priority(operators.peek())>=priority(s)&&!operators.peek().equals("(")) { if (!operators.peek().equals("(")) { String operator=operators.pop(); sb.append(operator).append(" "); output.push(operator); } } operators.push(s); } //如果讀入的操作符是")",則彈出從棧頂開始第一個"("及其之前的所有操作符 else if (s.equals(")")) { while (!operators.peek().equals("(")) { String operator=operators.pop(); sb.append(operator).append(" "); output.push(operator); } //彈出"(" operators.pop(); } } } //讀入的為非操作符 else { sb.append(s).append(" "); output.push(s); } } if (!operators.isEmpty()) { Iterator<String> iterator=operators.iterator(); while (iterator.hasNext()) { String operator=iterator.next(); sb.append(operator).append(" "); output.push(operator); iterator.remove(); } } String sum= calculate(); return sum; }
(3)根據后綴表達式計算結果

private static String calculate(){ LinkedList<String> mList=new LinkedList<>(); String[] postStr=sb.toString().split(" "); for (String s:postStr) { if (isOperator(s)) { if (!mList.isEmpty()) { int num1=Integer.valueOf(mList.pop()); int num2=Integer.valueOf(mList.pop()); int newNum=cal(num2,num1,s); mList.push(String.valueOf(newNum)); } } else { //數字則壓入棧中 mList.push(s); } } if (!mList.isEmpty()) { return mList.pop(); } return null; }
6、總結
在本次項目中,我建立了兩個java文件,分別是Main.java與Calculate_SE .java,Calculate_SE .java用於整體的方法實現,其中包含calaulate_AE(產生隨機運算式)、transferToPostfix(中綴表達式轉化為逆波蘭式)、calculate(計算逆波蘭式)等方法,然后利用Main調用Calculate_SE中的各個方法完成整體項目。實現小學生四則運算練習軟件的設計,加入了附加功能(括號運算),但未能實現分數運算,后期我會繼續學習改進,使其功能較為完善。
7、展示PSP
PSP2.1 | 任務內容 | 計划完成的時間(min) | 實際完成需要的時間(min) |
---|---|---|---|
PLanning | 計划 | 30 | 30 |
Estimate | 估計這個任務需要多少時間,並規划大致工作步驟 | 30 | 40 |
Developmet | 開發 | 240 | 360 |
Analysis | 需求分析(包括學習新技術) | 30 | 30 |
Design Spec | 生成設計文檔 | 10 | 15 |
Design Revie | 設計復審(和同事審核設計文檔) | 15 | 15 |
Coding Standard | 代碼規范 | 10 | 20 |
Design | 具體設計 | 30 | 45 |
Coding | 具體編碼 | 120 | 240 |
Code Review | 代碼復審 | 10 | 10 |
Test | 測試(自我測試,修改代碼,提交修改) | 20 | 30 |
Reporting | 報告 | 30 | 40 |
Test Report | 測試報告 | 20 | 20 |
Size Measurement | 計算工作量 | 5 | 5 |
Postmortem & Process Improvement Plan | 事后總結,並提出過程改機計划 | 10 | 15 |
8、項目心得
首先,感受到每個項目的分析階段特別重要,你的分析缺陷大就意味着你返工的可能性越大。當你對於一個項目的整體思路把握較好后,代碼編程時會流暢許多,所以我們一定要養成一個良好的開發習慣。其次,本次項目過程中,感覺特別對不起Java老師,好久沒有練習java語言,生疏了許多。這應該就是那句“學如逆水行舟,不進則退”吧。