Github項目地址:https://github.com/xiaobaot/wordcount/tree/master/sizeyusuan
團隊成員:謝家明(代碼生成) 謝竣(測試完善)
項目需求:
1. 使用 -n 參數控制生成題目的個數,例如
Myapp.exe -n 10
將生成10個題目。
2. 使用 -r 參數控制題目中數值(自然數、真分數和真分數分母)的范圍,例如
Myapp.exe -r 10
將生成10以內(不包括10)的四則運算題目。該參數可以設置為1或其他自然數。該參數必須給定,否則程序報錯並給出幫助信息。
3. 生成的題目中計算過程不能產生負數,也就是說算術表達式中如果存在形如e1 − e2的子表達式,那么e1 ≥ e2。
4. 生成的題目中如果存在形如e1 ÷ e2的子表達式,那么其結果應是真分數。
5. 每道題目中出現的運算符個數不超過3個。
6. 程序一次運行生成的題目不能重復,即任何兩道題目不能通過有限次交換+和×左右的算術表達式變換為同一道題目。例如,23 + 45 = 和45 + 23 = 是重復的題目,6 × 8 = 和8 × 6 = 也是重復的題目。3+(2+1)和1+2+3這兩個題目是重復的,由於+是左結合的,1+2+3等價於(1+2)+3,也就是3+(1+2),也就是3+(2+1)。但是1+2+3和3+2+1是不重復的兩道題,因為1+2+3等價於(1+2)+3,而3+2+1等價於(3+2)+1,它們之間不能通過有限次交換變成同一個題目。
生成的題目存入執行程序的當前目錄下的Exercises.txt文件,格式如下:
1. 四則運算題目1
2. 四則運算題目2
……
其中真分數在輸入輸出時采用如下格式,真分數五分之三表示為3/5,真分數二又八分之三表示為2’3/8。
7. 在生成題目的同時,計算出所有題目的答案,並存入執行程序的當前目錄下的Answers.txt文件,格式如下:
1. 答案1
2. 答案2
特別的,真分數的運算如下例所示:1/6 + 1/8 = 7/24。
8. 程序應能支持一萬道題目的生成。
9. 程序支持對給定的題目文件和答案文件,判定答案中的對錯並進行數量統計,輸入參數如下:
Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt
統計結果輸出到文件Grade.txt,格式如下:
Correct: 5 (1, 3, 5, 7, 9)
Wrong: 5 (2, 4, 6, 8, 10)
其中“:”后面的數字5表示對/錯的題目的數量,括號內的是對/錯題目的編號。為簡單起見,假設輸入的題目都是按照順序編號的符合規范的題目。
PSP開發耗時
| PSP2.1 |
Personal Software Process Stages |
預估耗時(分鍾) |
實際耗時(分鍾) |
| Planning |
計划 |
60 |
100 |
| · Estimate |
· 估計這個任務需要多少時間 |
100 |
120 |
| Development |
開發 |
600 |
660 |
| · Analysis |
· 需求分析 (包括學習新技術) |
120 |
150 |
| · Design Spec |
· 生成設計文檔 |
40 |
50 |
| · Design Review |
· 設計復審 (和同事審核設計文檔) |
50 |
60 |
| · Coding Standard |
· 代碼規范 (為目前的開發制定合適的規范) |
40 |
40 |
| · Design |
· 具體設計 |
60 |
60 |
| · Coding |
· 具體編碼 |
120 |
120 |
| · Code Review |
· 代碼復審 |
60 |
90 |
| · Test |
· 測試(自我測試,修改代碼,提交修改) |
60 |
60 |
| Reporting |
報告 |
90 |
90 |
| · Test Report |
· 測試報告 |
60 |
60 |
| · Size Measurement |
· 計算工作量 |
30 |
30 |
| · Postmortem & Process Improvement Plan |
· 事后總結, 並提出過程改進計划 |
30 |
30 |
| 合計 |
|
1520 |
1720 |
設計思路
1.我們首先想到的是整數化分數的運算,再對分子分母進行化簡,我們試圖生成兩個分子和兩個分母(分母至少一個為零時則全置為1,從而達到生成整數而用分數去運算的效果)來實現讓整數和分數的計算可以同步。
2.對分數(不論是結果還是題目)進行判斷,是假分數則化為帶分數的形式,是真分數保持不變。
3.通過對不同文件的操作輸出題目,答案以及統計答題者情況。
4.程序需求中的查重功能沒有實現。
具體代碼實現
main函數部分代碼:
public static void main(String[] args){ Scanner sc= new Scanner(System.in); System.out.println("請輸入產生幾以內的數字:"); range=sc.nextInt(); System.out.println("請輸入產生多少個運算表達式:"); int num=sc.nextInt(); int rightcount[]=new int[num+2]; int wrongcount[]=new int[num+2]; int right1=0; int wrong1=0; String[] results=new String[num];int i; for( i=0;i<num;i++){
/*具體的功能如下面的代碼(兩個class除外)*/
}
生成題目:
String expArr[]=new String[2];//定義生成的題目 int a= (int) (random.nextInt(range));//分子 int b= (int) (random.nextInt(range));//分母 int c= (int) (random.nextInt(range));//另一個分子 int d= (int) (random.nextInt(range));//另一個分母 int fuhao;//運算符 fuhao= (int) (random.nextInt(4)); if(b!=0&&d!=0) {//分母均不為0時生成帶有分數的計算題,同時計算結果 if(fuhao==0) { int fenzi=a*d+b*c; int fenmu=b*d; expArr[0]=biaodashi(a,b)+'+'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu); } if(fuhao==1&&a*d-b*c>=0) { int fenzi=a*d-b*c; int fenmu=b*d; expArr[0]=biaodashi(a,b)+'-'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu); } if(fuhao==1&&a*d-b*c<0) { int fenzi=b*c-a*d; int fenmu=b*d; expArr[0]=biaodashi(a,b)+'-'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu); } if(fuhao==2) { int fenzi=a*c; int fenmu=b*d; expArr[0]=biaodashi(a,b)+'×'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu); } if(fuhao==3&&c!=0) { int fenzi=a*d; int fenmu=b*c; expArr[0]=biaodashi(a,b)+'÷'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu); } if(fuhao==3&&c==0) { break; /*c=1; int fenzi=a*d; int fenmu=b*c; expArr[0]=biaodashi(a,b)+'÷'+biaodashi(c,d)+'='; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);*/ } } else {//分母至少一個為0時生成只含有整式的運算式,同時計算結果 b=1; d=1; if(fuhao==0) { int fenzi=a*d+b*c; int fenmu=b*d; expArr[0]=a+"+"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果 } if(fuhao==1&&a*d-b*c>=0) { int fenzi=a*d-b*c; int fenmu=b*d; expArr[0]=a+"-"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
} if(fuhao==1&&a*d-b*c<0) { int fenzi=b*c-a*d; int fenmu=b*d; expArr[0]=c+"-"+a+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
} if(fuhao==2) { int fenzi=a*c; int fenmu=b*d; expArr[0]=c+"×"+a+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
} if(fuhao==3&&c!=0) { int fenzi=a*d; int fenmu=b*c; expArr[0]=a+"÷"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);//計算結果
} if(fuhao==3&&c==0) { break;//排除分母為零的情況 /*c=1; int fenzi=a*d; int fenmu=b*c; expArr[0]=a+"÷"+c+"="; System.out.println(expArr[0]); results[i]=reductionofFraction(fenzi, fenmu);*/ }
對分數的處理:
public static String reductionofFraction(int a, int b) {// 結果的分數約分,用於計算結果 int y = 1; for (int i = a; i >= 1; i--) { if (a % i == 0 && b % i == 0) { y = i; break; } } int z = a / y;// 分子 int m = b / y;// 分母 if (z == 0) { return "0"; } if(m==1) return z+""; else return biaodashi(z,m); } public static String biaodashi(int a,int b) {//判斷假分數,並化假分數為帶分數 if(a>=b) { int c; c=a/b; int d; d=a%b; {if(d==0) {return c+"";} return c+"'"+d+"/"+b;} }return a+"/"+b; }
生成題目文件及答案文件:
FileWriter fw = null; try { File f=new File("Exersies.txt");//題目寫入 fw = new FileWriter(f, true); } catch (IOException e) { e.printStackTrace(); }if(expArr[0]!=null) { PrintWriter pw = new PrintWriter(fw); pw.println(i+1+"."+expArr[0]); pw.flush(); try { fw.flush(); pw.close(); fw.close(); } catch (IOException e) { e.printStackTrace(); }}FileWriter fn = null; try { File f=new File("Answer.txt");//答案寫入 fn = new FileWriter(f, true); } catch (IOException e) { e.printStackTrace(); }if(expArr[0]!=null) { PrintWriter pn = new PrintWriter(fn); pn.println(i+1+"."+results[i]); pn.flush(); try { fn.flush(); pn.close(); fn.close(); } catch (IOException e) { e.printStackTrace(); }}
統計並輸出答題者的情況:
System.out.println("輸入ok提交!");//答題完成后輸入ok即可提交 Scanner sc1=new Scanner(System.in); String submit=sc1.nextLine(); if(submit.equals("ok")){ String array[]=new String[num]; try { int k=0; FileReader fr = new FileReader("H://eclipse2//eclipse3//sizeyusuan//Your_answers.txt"); BufferedReader br = new BufferedReader(fr); String s ; while((s = br.readLine())!=null) {//讀取小學生的答案 array[k]=s; k++; }br.close(); fr.close(); }catch(IOException e){ System.out.println("指定文件不存在"); } for(int j=0;j<num;j++){ if(array[j].equals(results[j])) {//驗證答案,統計正確和錯誤的個數 rightcount[j]=j+1; right1++; } else { wrongcount[j]=j+1; wrong1++; } } FileWriter fg = null; try { //反饋正確與錯誤題目的信息 File f=new File("Grade.txt"); fg = new FileWriter(f, true); } catch (IOException e) { e.printStackTrace(); } PrintWriter pg = new PrintWriter(fg); pg.println(" "); pg.print("Correct:"+right1+"("); for (int j = 0; j <= num; j++) { if (rightcount[j] != 0) { pg.print(rightcount[j] + ","); } } pg.println(")"); pg.print("Wrong:"+wrong1+"("); for (int j = 0; j <= num; j++) { if (wrongcount[j] != 0) { pg.print(wrongcount[j] + ","); } } pg.print(")"); pg.flush(); try { fg.flush(); pg.close(); fg.close(); } catch (IOException e) { e.printStackTrace(); }}
測試運行
題目文件

答案文件

答題者答案文件

校對文件

項目小結
1.每道題目中出現的運算符個數我們只實現了單個運算符,當我們后來試圖擴展多個運算符的時候發現時間不夠了,因此只能上交較為簡單的版本。
2.查重功能以我們的算法和我們的能力感覺實現有難度,所以並不在我們的計划中。
3.遇到的困難主要是數組越界,通過嚴謹的檢查以及步步驗證的方式找出了錯誤並解決了。另一個須待解決的問題是生成題目的速度有些緩慢,因此完善了多次的算法來提高代碼的執行效率。
4.總的來說,在結對編程中我們有各自的想法,通過代碼的形式來進行人與人之間的交流不失為一種好的方法,在這個過程中我們培養了團隊協作的能力和與他人交際的能力,同時也促使自身的編程能力不斷提高,這使我們都受益匪淺。當然如果還有機會的話,我還是希望可以實現帶括號的運算式的生成以及答案的計算。
