源碼在Github的倉庫主頁連接地址:https://github.com/rucr9/rucrjava
看到這個題目,大概不少人會發出「切,這也太簡單了吧!有必要小題大作?」的感嘆!是的,僅僅做爲一道數學運算是沒難度,可是,如何實現智能出題並計算正確答案,爲大腦減壓呢?接下來,我將用java編寫程序實現小學四則運算。git
1.程序可接收一個輸入參數n,而後隨機產生n道加減乘除練習題;github
2.每一個數字在 0 和 100 之間,運算符在3個到5個之間;正則表達式
3.所出的練習題在運算過程當中不得出現負數與非整數;算法
4.將練習題和計算結果一塊兒輸出到文件中;express
5.當程序接收的參數爲4時,如下爲輸出文件示例:瀏覽器
用戶輸入須要出題的數量n,而後隨機產生n道加減乘除練習題,每一個數字在 0 和 100 之間,運算符在3個到5個之間,而且所出的練習題在運算過程當中不得出現負數與非整數;最後將練習題和運算結果輸出到result.txt文件中。dom
主類:Arithmetic,這個類主要是用戶輸入出題的數量,隨機產生練習題,並調用Expression類中的方法計算結果,最後輸出到result.txt文件中。學習
運算類:Calculate,此類規定了運算符的優先級和計算規則。測試
逆波蘭式轉換類:Expression,此類負責將中序表達式轉換爲右序表達式,並調用Calculate中的方法求值。
棧類:Stack,此類定義棧方法。
Arithmetic類
1 public static ArrayList<String> ss = new ArrayList<String>(); 2 3 public static void main(String[] args) throws Exception { 4 5 System.out.println("Input a number:"); 6 int count = new Scanner(System.in).nextInt(); 7 File file =new File("./result.txt"); 8 FileOutputStream fops=null ; 9 10 try { 11 fops = new FileOutputStream(file); 12 13 } catch (FileNotFoundException e) { 14 e.printStackTrace(); 15 } 16 PrintStream ps= new PrintStream(fops); 17 ps.println("201571030125"); 18 boolean f = true; 19 for (int i=0;i<count;i++) { 20 String data = Data(); 21 String input = data; 22 ss.add(input); 23 if (input.equals("q")) 24 break; 25 else { 26 Expression express = new Expression(input); 27 f = express.getResult(); 28 if(!f) i--; 29 else ps.println(data + "=" + express.getExpresult()); 30 } 31 } 32 } 33 34 35 //隨機產生算式 36 public static String Data() 37 { 38 Random rand =new Random(); 39 ArrayList<Integer> numlist = new ArrayList<Integer>(); 40 ArrayList<String> express = new ArrayList<String>(); 41 //產生隨機數 42 for(int i=0;i<5;i++) 43 { 44 numlist.add(rand.nextInt(100)+1); 45 } 46 //System.out.print(numlist); 47 String[] operator=new String[]{"+","-","*","/"}; 48 int size=numlist.size(); 49 String[] num=new String[size]; 50 for(int i=0;i<numlist.size();i++){ 51 num[i]=String.valueOf(numlist.get(i)); 52 } 53 String exp=""; 54 for(int j=0;j<num.length;j++) 55 { 56 express.add(num[j]); 57 express.add(operator[rand.nextInt(4)]); 58 } 59 //System.out.print(express); 60 61 for(int i=0;i<express.size()-1;i++) 62 exp+=express.get(i); 63 return exp; 64 }
Calulate類
1 // 判斷是否爲操做符號 2 public static boolean isOperator(String operator) { 3 if (operator.equals("+") || operator.equals("-") 4 || operator.equals("*") || operator.equals("/") 5 || operator.equals("(") || operator.equals(")")) 6 return true; 7 else 8 return false; 9 } 10 // 設置操做符號的優先級別 11 public static int priority(String operator) { 12 if (operator.equals("+") || operator.equals("-")) 13 return 1; 14 else if (operator.equals("*") || operator.equals("/")) 15 return 2; 16 else 17 return 0; 18 } 19 // 作2值之間的計算 20 public static String twoResult(String operator, String a, String b) { 21 try { 22 String op = operator; 23 String rs = new String(); 24 double x = Double.parseDouble(b); 25 double y = Double.parseDouble(a); 26 boolean f = true; 27 28 double z = 0.0; 29 if (op.equals("+")) 30 z = x + y; 31 else if (op.equals("-")) 32 z = x - y; 33 else if (op.equals("*")) 34 z = x * y; 35 else if (op.equals("/")) 36 { 37 if(y==0) { 38 y=1; 39 z=999999; 40 } 41 z = x / y; 42 if(z*y!=x) z=999999; 43 } 44 else 45 z = 999999; 46 if(z<0) z=999999; 47 if(z!=(int)z) z=999999; 48 return String.valueOf(z); 49 } catch (NumberFormatException e) { 50 System.out.println("input has something wrong!"); 51 return "Error"; 52 } 53 }
逆波蘭式轉換方法
1 private void toRight() { 2 Stack aStack = new Stack(); 3 String operator; 4 int position = 0; 5 while (true) { 6 if (Calculate.isOperator((String) expression.get(position))) { 7 if (aStack.top == -1 8 || ((String) expression.get(position)).equals("(")) { 9 aStack.push(expression.get(position)); 10 } else { 11 if (((String) expression.get(position)).equals(")")) { 12 while(true){ 13 if (aStack.top != -1&&!((String) aStack.top()).equals("(")) { 14 operator = (String) aStack.pop(); 15 right.add(operator); 16 }else{ 17 if(aStack.top != -1) 18 aStack.pop(); 19 break; 20 } 21 } 22 } else { 23 while(true){ 24 if (aStack.top != -1&& Calculate.priority((String) expression 25 .get(position)) <= Calculate 26 .priority((String) aStack.top()) 27 ) { 28 operator = (String) aStack.pop(); 29 if (!operator.equals("(")) 30 right.add(operator); 31 }else{ 32 break; 33 } 34 35 } 36 aStack.push(expression.get(position)); 37 } 38 } 39 } else 40 right.add(expression.get(position)); 41 position++; 42 if (position >= expression.size()) 43 break; 44 } 45 while (aStack.top != -1) { 46 operator = (String) aStack.pop(); 47 if(!operator.equals("(")) 48 right.add(operator); 49 } 50 }
逆波蘭式求值方法
1 boolean getResult() { 2 3 4 this.toRight(); 5 6 Stack aStack = new Stack(); 7 String op1, op2, is = null; 8 String temp=""; 9 Iterator it = right.iterator(); 10 while (it.hasNext()) { 11 is = (String) it.next(); 12 if (Calculate.isOperator(is)) { 13 op1 = (String) aStack.pop(); 14 op2 = (String) aStack.pop(); 15 temp = Calculate.twoResult(is, op1, op2); 16 double td = Double.parseDouble(temp.trim()); 17 if(td==999999.0){ 18 return false; 19 20 } 21 aStack.push(temp); 22 } else 23 aStack.push(is); 24 } 25 expresult = (String) aStack.pop(); 26 27 it = expression.iterator(); 28 while (it.hasNext()) { 29 String tempstr = (String) it.next(); 30 System.out.print(tempstr); 31 32 } 33 System.out.println("=" + expresult); 34 return true; 35 36 }
此項目看似簡單,但實際上要考慮的問題有不少,好比如何產生隨機數,隨機數和運算符如何結合,用什麼結構存儲數據,使用什麼方法計算表達式(正則表達式,逆波蘭式等等),如何去除不符合要求的運算式,如何處理異常等等。
起初看到題目時,感受這不就是加減乘除運算嘛,有什麼難的。可是,當具體設計的時候發現困難重重,必須思路清晰,邏輯縝密,寫代碼時纔不會東一下西一下,最後一團亂,連本身都搞不明白本身在幹嗎了,因此,拿到任何一個題目時都不要急於寫代碼,作好需求分析、設計實現等前期工做是很是重要的。
最後,提醒各位園友養成編輯過程當中隨時保存博客的習慣,以防手一抖、頭腦一發昏刷新網頁或者關閉瀏覽器,這可真的是前功盡棄啊!痛到欲哭無淚。。。本人就是犯了這樣的錯誤,致使重寫博客!!!
1.最後的計算結果都帶有小數點;
2.java自帶了棧類,我在這裏從新定義有些多餘;
3.產生的練習題都是5個運算數。
本項目參考逆波蘭式算法http://blog.csdn.net/yunxiang/article/details/1918717,並根據需求和本身的理解進行改進而成,若有好的建議,請多多指教!我將很是感謝!
PSP2.1 | 任務內容 | 計劃完成須要的時間(min) | 實際完成須要的時間(min) |
Planning | 計劃 | 15 | 20 |
Estimate | 估計這個任務須要多少時間,並規劃大體工做步驟 | 20 | 25 |
Development | 開發 | 120 | 180 |
Analysis | 需求分析 (包括學習新技術) | 15 | 10 |
Design Spec | 生成設計文檔 | 10 | 8 |
Design Review | 設計複審 (和同事審覈設計文檔) | 15 | 20 |
Coding Standard | 代碼規範 (爲目前的開發制定合適的規範) | 20 | 25 |
Design | 具體設計 | 30 | 35 |
Coding | 具體編碼 | 180 | 240 |
Code Review | 代碼複審 | 15 | 20 |
Test | 測試(自我測試,修改代碼,提交修改) | 20 | 25 |
Reporting | 報告 | 20 | 22 |
Test Report | 測試報告 | 5 | 5 |
Size Measurement | 計算工做量 | 5 | 10 |
Postmortem & Process Improvement Plan | 過後總結 ,並提出過程改進計劃 | 8 | 10 |