1. 程式人生 > >Java實現四則運算 謝雅淇 袁杏儀

Java實現四則運算 謝雅淇 袁杏儀

mex 同事 了解 必須 neo con 報錯 right spa

GitHub鏈接:https://github.com/3216004716/four-operations.git

項目相關要求

  1. 使用 -n 參數控制生成題目的個數,例如

    Myapp.exe -n 10 將生成10個題目。

  1. 使用 -r 參數控制題目中數值(自然數、真分數和真分數分母)的範圍,例如

    Myapp.exe -r 10

    將生成10以內(不包括10)的四則運算題目。該參數可以設置為1或其他自然數。該參數必須給定,否則程序報錯並給出幫助信息。

  1. 生成的題目中計算過程不能產生負數,也就是說算術表達式中如果存在形如e1 ? e2的子表達式,那麽e1 ≥ e2。

  2. 生成的題目中如果存在形如e1 ÷ e2的子表達式,那麽其結果應是真分數。

  3. 每道題目中出現的運算符個數不超過3個。

  4. 程序一次運行生成的題目不能重復,即任何兩道題目不能通過有限次交換+和×左右的算術表達式變換為同一道題目。

    生成的題目存入執行程序的當前目錄下的Exercises.txt文件,格式如下:

    1. 四則運算題目1

    2. 四則運算題目2

    其中真分數在輸入輸出時采用如下格式,真分數五分之三表示為3/5,真分數二又八分之三表示為2’3/8。

  1. 在生成題目的同時,計算出所有題目的答案,並存入執行程序的當前目錄下的Answers.txt文件,格式如下:

    1.答案1

    2.答案2

    特別的,真分數的運算如下例所示:1/6 + 1/8 = 7/24。

  1. 程序應能支持一萬道題目的生成。

  2. 程序支持對給定的題目文件和答案文件,判定答案中的對錯並進行數量統計,輸入參數如下:

    Myapp.exe -e <exercisefile>.txt -a <answerfile>.txt

    統計結果輸出到文件Grade.txt,格式如下:

      Correct: 5 (1, 3, 5, 7, 9)

      Wrong: 5 (2, 4, 6, 8, 10)

    其中“:”後面的數字5表示對/錯的題目的數量,括號內的是對/錯題目的編號。為簡單起見,假設輸入的題目都是按照順序編號的符合規範的題目。

PSP:

PSP2.1Personal Software Process Stages預估耗時(分鐘)實際耗時(分鐘)
Planning 計劃 10 15
· Estimate · 估計這個任務需要多少時間 10 15
Development 開發 1160 1510
· Analysis · 需求分析 (包括學習新技術) 200 400
· Design Spec · 生成設計文檔 60 60
· Design Review · 設計復審 (和同事審核設計文檔) 30 20
· Coding Standard · 代碼規範 (為目前的開發制定合適的規範) 30 60
· Design · 具體設計 60 90
· Coding · 具體編碼 600 700
· Code Review · 代碼復審 120 90
· Test · 測試(自我測試,修改代碼,提交修改) 60 90
Reporting 報告 120 150
· Test Report · 測試報告 80 90
· Size Measurement · 計算工作量 10 20
· Postmortem & Process Improvement Plan · 事後總結, 並提出過程改進計劃 30 40
合計 1290 1675

解題思路:

  • 取隨機操作數

  • 取隨機操作符

  • 生成表達式

  • 由表達式轉換為後綴表達式

  • 後綴表達式入棧,計算

  • 去重

  • 結果寫入文件

設計實現過程

  • Utils

    • RandomUtil 生成隨機操作數和隨機操作符

    • ExpressionUtil 生成表達式

    • CalculateUtil 封裝計算的方法

    • FileUtil 生成題目和答案的文檔

  • Calculate

    • calculateResult 用於計算結果

  • Expression

    • CheckExpression 檢查重復的表達式

    • MyExpression 表達式類

    • PostfixExpression 生成後綴表達式

代碼說明

  • RandomUtil類 獲取隨機操作數,用了Math.random()

// 獲取隨機操作數
    public static String getRandomOperand(int range) {
        String Operand = null;
        int index = (int) (Math.random() * 4);
        if (index == 0) {// 生成分數
            index = (int) (Math.random() * 3);
            if (index == 2) {// 生成假分數
                Operand = getImproperTractionNumber(range);
            } else {// 生成真分數
                Operand = getTruTractionNumber(range);
            }
        } else {
            Operand = getNaturalNumber(range);// 生成整數
        }
        return Operand;
    }
  • ExpressionUtil類 獲取隨機表達式

public static MyExpression getRandomExpression(int range) {
        // 獲取隨機表達式
        MyExpression myExpression = null;
        int index = (int) (Math.random() * 10);
        if (index <= 3) {
            myExpression = getOneOperExp(range);// 一個操作符
        } else if (index == 4) {// 三個操作符
            index = (int) (Math.random() * 2);
            if (index == 0) {
                myExpression = getThreeOperExp(range);
            } else {
                myExpression = getThreeOperExpWithBracket(range);
            }
        } else {// 兩個操作符
            index = (int) (Math.random() * 2);
            if (index == 0) {
                myExpression = getTwoOperExp(range);
            } else {
                myExpression = getTwoOperExpWithBracket(range);
            }
        }
        CaculateResult.caculate(myExpression);  // 計算結果
?
        return myExpression;
    }
  • PostfixExpression類 生成後綴表達式

private static ArrayList<String> generatePostfixExpression(String expression) {
        //生成String類型的後綴表達式
        String[] expressionArray = expression.split(" ");
        ArrayList<String> postfixExpression = new ArrayList<String>();
        Stack<String> stack = new Stack<String>();
        for (int i = 0; i < expressionArray.length; i++) {
            String item = expressionArray[i];
            String temp = "";
            switch (item) {
            case "(":
                stack.push(item);
                break;
            case ")":
                while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
                    postfixExpression.add(temp);
                }
                break;
            case "+":
            case "-":
                while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
                    postfixExpression.add(temp);
                }
                if (temp.equals("(")) {
                    stack.push(temp);
                }
                stack.push(item);
                break;
            case "×":
            case "÷":
                while ((stack.size() != 0) && !((temp = stack.pop()).equals("("))) {
                    if (temp.equals("×") || temp.equals("÷")) {
                        postfixExpression.add(temp);
                    } else {
                        stack.push(temp);
                        break;
                    }
                }
                if (temp.equals("(")) {
                    stack.push(temp);
                }
                stack.push(item);
                break;
            default:
                postfixExpression.add(item);
            }
        }
        while (stack.size() != 0) {
            postfixExpression.add(stack.pop());
        }
        return postfixExpression;
    }
  • CalculateResult類 計算後綴表達式

public class CaculateResult {

    public static void caculate(MyExpression myExpression) {
        PostfixExpression.toPostfixExpression(myExpression);
        ArrayList<String> postfixExpression = myExpression.getPostfixExpression();
        String temp = "";
        Stack<String> s = new Stack<>();

        String rightOperand = null;
        String leftOperand = null;
        int result = 0;
        int a1, a2, b1, b2 = 0;
        int denominator = 0;
        int numerator = 0;
        a: for (int i = 0; i < postfixExpression.size(); i++) {

            String item = postfixExpression.get(i);
            switch (item) {
            case "+":
                rightOperand = s.pop();
                leftOperand = s.pop();
                if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    result = Integer.parseInt(rightOperand) + Integer.parseInt(leftOperand);
                    temp = String.valueOf(result);
                } else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
                    denominator = CaculateUtil.getDenominator(leftOperand);
                    numerator = CaculateUtil.getNumerator(leftOperand);
                    numerator = Integer.parseInt(rightOperand) * denominator + numerator;
                    temp = numerator + "/" + denominator;
                } else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    denominator = CaculateUtil.getDenominator(rightOperand);
                    numerator = CaculateUtil.getNumerator(rightOperand);
                    numerator = Integer.parseInt(leftOperand) * denominator + numerator;
                    temp = numerator + "/" + denominator;
                } else {
                    a1 = CaculateUtil.getDenominator(rightOperand);
                    a2 = CaculateUtil.getNumerator(rightOperand);
                    b1 = CaculateUtil.getDenominator(leftOperand);
                    b2 = CaculateUtil.getNumerator(leftOperand);
                    numerator = a1 * b2 + a2 * b1;
                    denominator = a1 * b1;
                    temp = numerator + "/" + denominator;
                }
                s.push(temp);
                break;

            case "×":
                rightOperand = s.pop();
                leftOperand = s.pop();
                if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    result = Integer.parseInt(rightOperand) * Integer.parseInt(leftOperand);
                    temp = String.valueOf(result);
                } else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
                    numerator = CaculateUtil.getNumerator(leftOperand);
                    denominator = CaculateUtil.getDenominator(leftOperand);
                    numerator = numerator * Integer.parseInt(rightOperand);
                    temp = numerator + "/" + denominator;
                } else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    numerator = CaculateUtil.getNumerator(rightOperand);
                    denominator = CaculateUtil.getDenominator(rightOperand);
                    numerator = numerator * Integer.parseInt(leftOperand);
                    temp = numerator + "/" + denominator;
                } else {
                    a1 = CaculateUtil.getDenominator(rightOperand);
                    a2 = CaculateUtil.getNumerator(rightOperand);
                    b1 = CaculateUtil.getDenominator(leftOperand);
                    b2 = CaculateUtil.getNumerator(leftOperand);
                    numerator = a2 * b2;
                    denominator = a1 * b1;
                    temp = numerator + "/" + denominator;
                }
                s.push(temp);
                break;

            case "-":
                leftOperand = s.pop();
                rightOperand = s.pop();
                int inta, intb = 0;
                if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    inta = Integer.parseInt(rightOperand);
                    intb = Integer.parseInt(leftOperand);
                    result = inta - intb;
                    temp = String.valueOf(result);
                } else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
                    inta = Integer.parseInt(rightOperand);
                    numerator = CaculateUtil.getNumerator(leftOperand);
                    denominator = CaculateUtil.getDenominator(leftOperand);
                    numerator = inta * denominator - numerator;
                    temp = numerator + "/" + denominator;
                } else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    intb = Integer.parseInt(leftOperand);
                    numerator = CaculateUtil.getNumerator(rightOperand);
                    denominator = CaculateUtil.getDenominator(rightOperand);
                    numerator = numerator - intb * denominator;
                    temp = numerator + "/" + denominator;
                } else {
                    a1 = CaculateUtil.getDenominator(rightOperand);
                    a2 = CaculateUtil.getNumerator(rightOperand);
                    b1 = CaculateUtil.getDenominator(leftOperand);
                    b2 = CaculateUtil.getNumerator(leftOperand);
                    numerator = a2 * b1 - a1 * b2;
                    denominator = a1 * b1;
                    temp = numerator + "/" + denominator;
                }
                if (temp.contains("-")||temp.equals("0")) {
                    myExpression.setCheckAnswer(false);
                    break a;
                }
                s.push(temp);
                break;

            case "÷":
                leftOperand = s.pop();
                rightOperand = s.pop();
                int integer_a = 0, integer_b = 0;
                if (CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    integer_a = Integer.parseInt(rightOperand);
                    integer_b = Integer.parseInt(leftOperand);
                    if (integer_b == 0) {
                        break;
                    } else if ((integer_a % integer_b) == 0) {
                        result = integer_a / integer_b;
                        temp = String.valueOf(result);
                    } else {
                        numerator = integer_a;
                        denominator = integer_b;
                        temp = numerator + "/" + denominator;
                    }
                } else if (CaculateUtil.isNumeric(rightOperand) && !CaculateUtil.isNumeric(leftOperand)) {
                    integer_a = Integer.parseInt(rightOperand);
                    numerator = CaculateUtil.getNumerator(leftOperand);
                    denominator = CaculateUtil.getDenominator(leftOperand);
                    int temp1 = numerator;
                    numerator = integer_a * denominator;
                    denominator = temp1;
                    temp = numerator + "/" + denominator;
                } else if (!CaculateUtil.isNumeric(rightOperand) && CaculateUtil.isNumeric(leftOperand)) {
                    integer_b = Integer.parseInt(leftOperand);
                    numerator = CaculateUtil.getNumerator(rightOperand);
                    denominator = CaculateUtil.getDenominator(rightOperand);
                    denominator = denominator * integer_b;
                    temp = numerator + "/" + denominator;
                } else {
                    a1 = CaculateUtil.getDenominator(rightOperand);
                    a2 = CaculateUtil.getNumerator(rightOperand);
                    b1 = CaculateUtil.getDenominator(leftOperand);
                    b2 = CaculateUtil.getNumerator(leftOperand);
                    numerator = a2 * b1;
                    denominator = a1 * b2;
                    temp = numerator + "/" + denominator;
                }
                s.push(temp);
                break;

            default:
                s.push(item);
                break;
            }
        }
        myExpression.setResult(CaculateUtil.reduceFractiong(temp));
    }
}
  • CheckExpression類 檢查重復的表達式

public class CheckExpression {
?
    public static boolean checkRepeated(MyExpression expression1, MyExpression expression2) {
        boolean flag = true;
        if (expression1.getPostfixExpression().size() == expression2.getPostfixExpression().size()) {
            if (expToString(expression1.getPostfixExpression()).equals(expToString(expression2.getPostfixExpression()))
                    || changePosition(expression1).equals(expToString(expression2.getPostfixExpression()))) {
                flag = false;
            }
        }
        return flag;
    }
?
    static String changePosition(MyExpression expression) {
        ArrayList<String> postfixExpression = expression.getPostfixExpression();
        String firstOperator = getFirstOperator(postfixExpression);
        if (firstOperator.equals("+") || firstOperator.equals("×")) {
            int index = postfixExpression.indexOf(firstOperator);
            String temp = postfixExpression.get(index - 1);
            postfixExpression.set(index - 1, postfixExpression.get(index - 2));
            postfixExpression.set(index - 2, temp);
        }
?
        return expToString(postfixExpression);
    }
?
    static String getFirstOperator(ArrayList<String> postfixExpression) {
        String operator = "";
        for (int i = 0; i < postfixExpression.size(); i++) {
            String item = postfixExpression.get(i);
            if (item.equals("+") || item.equals("-") || item.equals("×") || item.equals("÷")) {
                operator = item;
                break;
            }
        }
        return operator;
    }
?
    public static String expToString(ArrayList<String> PostfixExpression) {
        String string = null;
        for (int i = 0; i < PostfixExpression.size(); i++) {
            string += PostfixExpression.get(i);
        }
        return string;
    }
}

運行結果

技術分享圖片

技術分享圖片

項目小結

  • 謝雅淇:我覺得這次程序的編寫,我只是在為了解決問題而寫方法的代碼,沒有很好地融入面向對象的思想。還有在寫代碼之前就要把思路理清楚,不然代碼就會寫的很亂,不僅會浪費時間,還會把代碼寫得非常冗長,可觀性比較差。這次作業的結對隊友,從討論需求到編寫代碼的過程中都幫助了我很多,我覺得我需要提升的地方還有很多,以後還需要繼續努力,多加練習。

  • 袁杏儀:我覺得這次程序的編寫,讓我對開發程序有了更深入的了解,體會到溝通與合作的重要性,同時也感受到團隊開發的樂趣,還收獲了真摯的友誼。這次作業,讓我感觸最深的是我們寫完代碼後測試時,得出結果然後進行驗算,檢查出錯答案並對源代碼進行修改的過程,每一次修改,一步步得出正確的結果,這讓我非常有成就感。

Java實現四則運算 謝雅淇 袁杏儀