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


源碼在Github的倉庫主頁鏈接地址:https://github.com/rucr9/rucr

  看到這個題目,大概很多人會發出“切,這也太簡單了吧!有必要小題大做?”的感嘆!是的,僅僅作為一道數學運算是沒難度,但是,如何實現智能出題並計算正確答案,為大腦減壓呢?接下來,我將用java編寫程序實現小學四則運算。

 需求分析

  1.程序可接收一個輸入參數n,然后隨機產生n道加減乘除練習題;

  2.每個數字在 0 和 100 之間,運算符在3個到5個之間;

  3.所出的練習題在運算過程中不得出現負數與非整數;

  4.將練習題和計算結果一起輸出到文件中;

  5.當程序接收的參數為4時,以下為輸出文件示例:

  

功能設計

  用戶輸入需要出題的數量n,然后隨機產生n道加減乘除練習題,每個數字在 0 和 100 之間,運算符在3個到5個之間,並且所出的練習題在運算過程中不得出現負數與非整數;最后將練習題和運算結果輸出到result.txt文件中。

設計實現

  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

      

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM