小學四則運算練習(JAVA編寫)

源碼在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

設計實現

  1.類

  主類:Arithmetic,這個類主要是用戶輸入出題的數量,隨機產生練習題,並調用Expression類中的方法計算結果,最後輸出到result.txt文件中。學習

  運算類:Calculate,此類規定了運算符的優先級和計算規則。測試

  逆波蘭式轉換類:Expression,此類負責將中序表達式轉換爲右序表達式,並調用Calculate中的方法求值。

  棧類:Stack,此類定義棧方法。

  2.程序執行流程

測試運行

                                             

核心代碼

  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,並根據需求和本身的理解進行改進而成,若有好的建議,請多多指教!我將很是感謝!

PSP

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
相關文章
相關標籤/搜索