1. 程式人生 > >2016012015+小學四則運算練習軟件項目報告

2016012015+小學四則運算練習軟件項目報告

乘除 -c san 產生 合法性 需求 括號 除法 pop

1.倉庫地址:https://git.coding.net/FrrLolix/Calculate.git

2.需求分析:

  ①程序接受一個輸入的參數n後,隨機生成n道四則運算式,其中要保證生成的運算式的運算符在3-5個之間,同時程序對生成的運算式自動求解,結果和運算式一同輸出到result.txt文件中。

  ②因為面向對象是小學生,所以要保證生成的運算式中不出現負數和小數,運算的結果也不能出現負數和小數。

  ③程序需要判斷輸入的參數n是否合法,在不合法時要進行一定的處理。

  ④在原有的基礎上,生成的運算式隨機性的帶有括號和真分數。

3.功能設計:

  ①基本功能:

    Ⅰ程序接收參數n,並對n的合法性作出判斷,若出現錯誤則提示。

    Ⅱ自動生成n個運算式,並計算得出結果。

    Ⅲ將計算後的結果與運算式一同存入txt文件中,保存在指定目錄下。

  ②擴展功能:

    Ⅰ由於面向對象是小學生,因此數字在0-100之間。

    Ⅱ隨機產生括號並保證括號的合法有效性。

    Ⅲ加入分數運算式,並且保證計算前後都是真分數,且不可化簡。

4.設計實現:

  ①整體思路:

    Ⅰ四則運算:首先產生5個隨機數和一個flag作為標誌,flag的值為隨機0-3,分別代表了不同數量的運算符和分數運算,確定了flag的值後,產生隨機的運算符將數字連接,構成運算式,再將運算符和數字拆分,利用兩個棧分別放置,將原本的運算式轉化成後綴表達式,從而進行計算,這也是逆波蘭表達式的計算方法。

    Ⅱ帶括號計算:以3個運算符的計算為例,括號只能存在於前兩個數字和後兩個數字中,因此設置location這一參數,location為0時,括號在前,location為1時括號在後,分別進行討論,確定括號的位置,生成帶括號的運算式,在後續計算過程中,註意要增加括號的入棧和出棧操作。

    Ⅲ真分數的計算:對於真分數,首先隨機產生0-100的某個數,然後隨機產生一個比剛剛生成的數小的數,通過輾轉相除法,生成真分數並輸出。

  對於整體而言,我只使用了一個類,通過這個類來調用不同的方法解決問題。

技術分享圖片

  ②設計的函數:

    Ⅰ構成3個運算數的運算式的方法: three(int n1,int n2,int n3)

    Ⅱ構成4個運算數的運算式的方法:four(int n1,int n2,int n3,int n4)

    Ⅲ構成5個運算數的運算式的方法:five(int n1,int n2,int n3,int n4,int n5)

    Ⅳ實現計算的方法:Calculate(String s)

    Ⅴ分式化簡的方法:gcd(int a,int b)

5.代碼詳情:

  ①生成表達式的算法:

    Ⅰ這裏使用一個循環,flag用於判斷每次循環產生的結果,根據flag的不同調用不同的方法

for(i=0;i<n;i++){
    int n1=ran.nextInt(100);//生成一個0-100的整數
    int n2=ran.nextInt(100);
    int n3=ran.nextInt(100);
    int n4=ran.nextInt(100);
    int n5=ran.nextInt(100);
    int flag=ran.nextInt(4);//隨機生成一個0-3的整數,0表示3個運算數,1表示4個運算數,2表示5個運算數,3表示分數計算

    Ⅱ此處是flag=3時,分數的生成方法

n1=1+ran.nextInt(101);
n2=1+ran.nextInt(101);
n3=1+ran.nextInt(101);
int M,Z;
int x1,x2,x3;
x1=1+ran.nextInt(n1);//生成一個比分母n1小的分子,實現真分數
x2=1+ran.nextInt(n2);//生成一個比分母n2小的分子,實現真分數
x3=1+ran.nextInt(n3);//生成一個比分母n3小的分子,實現真分數
Z=x1*n2*n3+x2*n1*n3+x3*n1*n2;
M=n1*n2*n3;
String d=gcd(Z,M);
s=x1+"/"+n1+"+"+x2+"/"+n2+"+"+x3+"/"+n3+"="+d;
pw.write(s+"\r\n"); // \r\n即為換行
    Ⅲ此處是3個運算符是運算式的生成方法,我在這裏進行了討論,加入了是否有括號的兩種情況,對於括號的位置進行設定,隨後輸出不同的結果,此處代碼較長,只展示一部分,詳細的可以在Coding.net上查詢
String s1= new String();
Random ran = new Random();
int sign1=ran.nextInt(4);//隨機生成一個0-3的整數,0表示加法,1表示減法,2表示乘法,3表示除法
int sign2=ran.nextInt(4);
int sign3=ran.nextInt(2);//如果是1表示有括號,如果是0 表示無括號
int sign4=ran.nextInt(2);//如果是1表示產生分式,如果是0 表示整式。

if(sign1==sign2)
{
    sign2=(sign1+1)%3;//保證兩個運算符不相同。
}

if(sign3==0)//表示無括號
{
    //下面的過程為排除,除不整的,還有分母為0,

    if(sign2==3)
    {
        if(n3==0)//如果分母為0
            n3=1+ran.nextInt(100);//隨機生成一個1-100的整數
        while(n2%n3!=0)
        {
            n2=ran.nextInt(100);
        }
    }


  ②計算方法

    Ⅰ計算方法我采用了逆波蘭表達式的算法,這一部分是之前困擾我最久的地方,起初想了許多方法來嘗試,但都有些繁瑣,實施起來並不是很容易,因此我也在其他博客上參考學習了許多,最終選定了逆波蘭表達式,逆波蘭表達式的思路為
  1.遇到操作數:直接輸出(添加到後綴表達式中)
  2.棧為空時,遇到運算符,直接入棧
  3.遇到左括號:將其入棧
  4.遇到右括號:執行出棧操作,並將出棧的元素輸出,直到彈出棧的是左括號,左括號不輸出。
  5.遇到其他運算符:加減乘除:彈出所有優先級大於或者等於該運算符的棧頂元素,然後將該運算符入棧
  6.最終將棧中的元素依次出棧,輸出。
  下面截取了遇到等號時的代碼處理。
case ‘(‘: {
                        stack2.push(String.valueOf(c));//如果是(   轉化為字符串壓入字符棧
                        break;
                    }
                    case ‘)‘: {//遇到右括號了計算,因為(的優先級最高
                        String stmp = stack2.pop();//如果是),將符號棧棧頂元素取到
                        while (!stack2.isEmpty() && !stmp.equals("(")) { //當前符號棧裏面還有+ - * /
                            int a = stack1.pop();  //取操做數a,b
                            int b = stack1.pop();
                            int sresulat = calculate(b, a, stmp);
                            if(sresulat<0)
                                return  -1;
                            stack1.push(sresulat);//將結果壓入棧
                            stmp = stack2.pop();//符號指向下一個計算符號
                        }
                        break;
                    }
6.測試運行:
  進入src文件下,輸入javac -encoding utf-8 Main.java 編譯出相應的class文件,再輸入java Main 進行測試:

技術分享圖片技術分享圖片


7.不足與改進:
  在算法的實現過程中,雖然經過了不斷的修改和調整,但目前仍然存在著許多不足:

  1.括號的處理,只是處理了幾種特殊情況,並沒有做到括號的隨機並合理,沒有涉及到多重括號的生成和處理,這也是以後改進的一個方向。

  2.在出題的過程中,我的方法是將不同數量的運算符的算法之間分離開,造成算法的延展性較差,目前也參考了同學們的代碼,發現自己的代碼如果擴展到10個運算符的情況,會很麻煩,這是接下來需要改進的一點。

  3.在最開始進行算法的分析的時候,沒有註意題目的要求,也沒有看到老師推薦的調度場算法,因此,在計算上大費周章,這是今後要避免的一個問題,對於項目要求一定要認真理解。

8.項目總結:

  1.在算法的編寫過程中,采用了書中和老師所推薦的“逐步求精”的設法方法,將一個項目分解成幾個不同的小問題,通過編寫不同的方法來逐步解決每個問題,各個方法相互配合,循序漸進,最終達成自己想要的結果。

  2.對於算法編寫中出現的許多問題,進行了思考和改進,並且對於項目的延展性有了更深的理解,我的算法延展性不強,這是以後和強化的一點。

9.PSP展示
  

PSP2.1

任務內容

計劃共完成需要的時間(min)

實際完成需要的時間(min)

Planning

計劃

8

10

· Estimate

· 估計這個任務需要多少時間,並規劃大致工作步驟

8

6

Development

開發

450

600

· Analysis

· 需求分析 (包括學習新技術)

20

30

· Design Spec

· 生成設計文檔

10

10

· Design Review

· 設計復審 (和同事審核設計文檔)

5

5

· Coding Standard

· 代碼規範 (為目前的開發制定合適的規範)

3

5

· Design

· 具體設計

10

20

· Coding

· 具體編碼

350

500

· Code Review

· 代碼復審

10

20

· Test

· 測試(自我測試,修改代碼,提交修改)

15

30

Reporting

報告

10

30

· Test Report

· 測試報告

5

10

· Size Measurement

· 計算工作量

1

1

· Postmortem & Process Improvement Plan

· 事後總結, 並提出過程改進計劃

5

15


    
  
 

2016012015+小學四則運算練習軟件項目報告