Java實現小學四則運算練習


 Github項目地址:https://github.com/feser-xuan/Arithmetic.git
1、需求分析
   軟件基本功能要求如下:
  • 程序可接收一個輸入參數n,然后隨機產生n道加減乘除練習題,每個數字在 0 和 100 之間,運算符在3個到5個之間。
  • 為了讓小學生得到充分鍛煉,每個練習題至少要包含2種運算符。同時,由於小學生沒有分數與負數的概念,你所出的練習題在運算過程中不得出現負數與非整數,比如不能出 3/5+2=2.6,2-5+10=7等算式。
  • 練習題生成好后,將你的學號與生成的n道練習題及其對應的正確答案輸出到文件“result.txt中,不要輸出額外信息文件目錄與程序目錄一致。
  • 當程序接收的參數為4時,以下為輸出文件示例。
  • 軟件附加功能要求如下:(請有余力的同學完成)
  • 支持有括號的運算式,包括出題與求解正確答案。注意,算式中存在的括號必須大於2個,且不得超過運算符的個數。
  • 擴展程序功能支持真分數的出題與運算,例如:1/6 + 1/8 + 2/3= 23/24。注意在實現本功能時,需支持運算時分數的自動化簡,比如 1/2+1/6=2/3,而非4/6。

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


免責聲明!

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



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