- 為了讓小學生得到充分鍛煉,每個練習題至少要包含2種運算符。同時,由於小學生沒有分數與負數的概念,你所出的練習題在運算過程中不得出現負數與非整數,比如不能出 3/5+2=2.6,2-5+10=7等算式。
- 練習題生成好后,將你的學號
- 當程序接收的參數為4時,以下為輸出文件示例。
2、功能分析
- 使用Java中提供的Random類,隨機產生0-100的正整數,並與隨機產生的四則運算符號相結合,構成隨機的四則運算。
- 由於小學並沒有接觸到負整數,故隨機計算結果為負的除去。
- 當產生符合要求的四則運算題目時,計算正確答案並輸出到名為result.txt的文件中。
3、設計實現
4、測試運行
5、核心代碼
- 隨機生成四則運算表達式:
1 int[] number_temp = new int[rand.nextInt(2)+3]; 2 String[] str_temp = new String[number_temp.length-1]; 3 for(int i=0;i<number_temp.length;i++) 4 { 5 if(i<number_temp.length-1) 6 { 7 number_temp[i]=rand.nextInt(100); 8 list_temp.add(String.valueOf(number_temp[i])); 9 str_temp[i]=operator[rand.nextInt(4)]; 10 list_temp.add(str_temp[i]); 11 12 } 13 else 14 { 15 number_temp[i]=rand.nextInt(100); 16 list_temp.add(String.valueOf(number_temp[i])); 17 } 18 }
- 用調度場算法產生逆波蘭式:
public static ArrayList<String> produce_RPN(ArrayList<String> list_temp) { int t=0,i=0; String tmp; Tack mytack = new Tack(20); ArrayList<String> lt_temp = new ArrayList<String>(); while(true) { tmp = list_temp.get(i++); if(isInteger(tmp)) { lt_temp.add(tmp); } else{ if(mytack.myisempty()) { mytack.mypush(tmp); } else{ if(isCPriority(tmp, mytack.mypeek())) mytack.mypush(tmp); else{ lt_temp.add(mytack.mypop()); mytack.mypush(tmp); } } } if(i>=list_temp.size()) { while(!mytack.myisempty()) lt_temp.add(mytack.mypop()); System.out.println(transform_string(list_temp)); list_temp = lt_temp; System.out.println(list_temp); return list_temp; } } }
- 用逆波蘭式,計算表達式的結果:
public static int calculate_RPN(ArrayList<String> list_temp) { int i=0,t; double a=0,b=0; String l_temp; Stack sk=new Stack(20); for(t=0;t<list_temp.size();t++) { l_temp = list_temp.get(i++); if(!isInteger(l_temp)) { b = sk.mypop(); a = sk.mypop(); switch(l_temp) { case "+":sk.mypush(a+b);break; case "-":sk.mypush(a-b);break; case "*":sk.mypush(a*b);break; case "/": if(b==0) return -1; sk.mypush(a/b);break; } System.out.println("st.mytop: "+sk.mypeek()); } else{ sk.mypush((double)Integer.parseInt(l_temp)); } } if(!sk.myisempty()) { a = sk.mypop(); b = a-(int)a; System.out.println("a: "+a); if(a>0 && b==0 ) { return (int)a; } else return -1; } else return -1; }
- 當計算結果為正整數時,添加到數組list。反之則重復上述步驟:
count=calculate_RPN(produce_RPN(list_temp)); if(count !=-1) { list_temp.add(" = "+count); list.add(transform_string(list_temp)); number_n--; list_temp.clear(); } else list_temp.clear();
- 當產生適當符合要求的表達式時,現將自己的學號、姓名寫到result.txt文件中,再將產生的表達式寫到result.txt文件中:
try { outSTr = new FileOutputStream(file1); Buff = new BufferedOutputStream(outSTr); try { Buff.write("201571030104 丁煒軒".getBytes()); Buff.write("\r\n".getBytes()); } catch (IOException e) { e.printStackTrace(); } for (int i = 0; i < list.size(); i++) { try { Buff.write(list.get(i).getBytes()); Buff.write("\r\n".getBytes()); } catch (IOException e) { e.printStackTrace(); i--; } } Buff.flush(); Buff.close(); } catch (IOException e) { e.printStackTrace(); } //Buff.close(); try { outSTr.close(); } catch (IOException e) { e.printStackTrace(); } for (int i = 0; i < list.size(); i++) { System.out.print(list.get(i)); System.out.println(); } System.out.print("計算完畢!");
- 到這時候,result.txt文件中已經就有了我們需要的四則運算表達式,以及正確的結果。
- 還有幾個小的函數,這里簡單說一下:
- 1.判斷字符串是否為正整數:
public static boolean isInteger(String str) { for (int i = str.length();--i>=0;){ if (!Character.isDigit(str.charAt(i))){ return false; } } return true; }
- 2.判斷運算符號的優先級順序:
public static boolean isCPriority(String str,String s) { if((str+s).equals("*+") || (str+s).equals("*-") || (str+s).equals("/+") || (str+s).equals("/-")) return true; else return false; }
- 3.將動態數組轉換為字符串類型:
public static String transform_string(ArrayList<String> list_temp) { String s=""; for(int i=0;i<list_temp.size();i++) { s+=list_temp.get(i); } return s; }
- 在本次實驗中,重要用到了棧:
-
static class Stack { int mytop; double stk[]; public Stack(int num) { mytop=-1; stk=new double[num]; } /*出棧*/ double mypop() { double peek=stk[mytop]; mytop--; return peek; } /*入棧*/ void mypush(double x) { mytop++; stk[mytop]=x; } /*判空*/ Boolean myisempty() { if(mytop==-1) return true; else return false; } /*取棧頂元素*/ double mypeek() { double peek=stk[mytop]; return peek; } /*棧大小*/ int mysize() { return mytop+1; } } static class Tack { int mytop; String tk[]; public Tack(int num) { mytop=-1; tk=new String[num]; } /*出棧*/ String mypop() { String peek=tk[mytop]; mytop--; return peek; } /*入棧*/ void mypush(String x) { mytop++; tk[mytop]=x; } /*判空*/ Boolean myisempty() { if(mytop==-1) return true; else return false; } /*取棧頂元素*/ String mypeek() { String peek=tk[mytop]; return peek; } /*棧大小*/ int mysize() { return mytop+1; } }
6、總結
在本次實驗中,主要在代碼完成、調試中花了很多時間。我感覺一方面由於長時間不使用Java語言編寫程序,對於Java語法結構、類的定義、函數的構造等知識方面都嚴重匱乏。一方面還是對於軟件工程這門課理解略有偏差。不過在老師,以及助教老師的共同幫助下,我學到了一些書本上學不到的知識。值此,由衷的感謝老師們對於我的鼓勵、幫助、以及肯定,我會繼續發揮自己的長處,彌補自己不足的地方,為了祖國美好的明天,讓我們共同努力!
PSP2.1 |
任務內容 |
計划完成需要的時間(min) |
實際完成需要的時間(min) |
Planning |
計划 |
30 |
46 |
· Estimate |
· 估計這個任務需要多少時間,並規划大致工作步驟 |
30 |
46 |
Development |
開發 |
160 |
200 |
·· Analysis |
需求分析 (包括學習新技術) |
20 |
20 |
· Design Spec |
· 生成設計文檔 |
15 |
20 |
· Design Review |
· 設計復審 (和同事審核設計文檔) |
5 |
10 |
· Coding Standard |
代碼規范 (為目前的開發制定合適的規范) |
20 |
20 |
· Design |
具體設計 |
30 |
30 |
· Coding |
具體編碼 |
60 |
80 |
· Code Review |
· 代碼復審 |
5 |
10 |
· Test |
· 測試(自我測試,修改代碼,提交修改) |
5 |
10 |
Reporting |
報告 |
60 |
80 |
·· Test Report |
· 測試報告 |
30 |
40 |
· Size Measurement |
計算工作量 |
15 |
20 |
· Postmortem & Process Improvement Plan |
· 事后總結 ,並提出過程改進計划 |
15 |
20 |