1. 程式人生 > >演算法與資料結構設計周作業——大整數運算器

演算法與資料結構設計周作業——大整數運算器

這次的演算法與資料結構設計周作業題目比較簡單,一個是求眾數與重數,另一個題目則為大整數運算器,由於圖形化介面不是硬性要求,所以專案不使用GUI,而是直接在命令列執行,具體題目如下:

  1. 眾數問題

給定含有n個元素的多重集合S,每個元素在S中出現的次數稱為該元素的重數,S中重數最大的元素稱為眾數。 例如,S={1, 2 ,2 ,2 ,3 ,5},S的眾數是2,該眾數的重數為3。 要求對於給定的由n個自然陣列成的多重集合S,計算S的眾數及其重數。

實現該問題並不難,使用Java的HashMap建立鍵值對,將數字最為key,出現的次數作為value,遍歷一次陣列即可確定眾數以及重數,程式碼如下。

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Unity {

    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(2);
        list.
add(2); list.add(2); list.add(13); list.add(1); list.add(1); Map<String, Integer> map = unity(list); System.out.println(map); } private static Map<String, Integer> unity(List<Integer> list) { Map<Integer, Integer>
map = new HashMap<>(); int max = list.get(0); int maxNum = 1; for (int a : list) { if (map.containsKey(a)) { map.put(a, map.get(a) + 1); if (maxNum < map.get(a)) { maxNum = map.get(a); max = a; } } else { map.put(a, 1); } } Map<String, Integer> maxMap = new HashMap<>(); maxMap.put("眾數", max); maxMap.put("重數", maxNum); return maxMap; } }
  1. 大整數運算器

(一)課題內容 實現一個簡單的大整數算術運算程式。主要功能計算兩個大整數(20位)的加減法等算術運算,按指定的格式輸出結果。通過此課題,熟練掌握字串、格式輸出、檔案的各種操作,以及基本的計算演算法思想的應用。 (二)課題要求

  1. 基本要求 (1) 輸入功能:能實現從鍵盤或文字檔案輸入代表大整數的字串並用合適的結構儲存,能實現輸入整個表示式(含大整數和相應的運算子)。 (2) 輸出功能:將算式及計算結果按照一定格式批量輸出到螢幕及另一個文字檔案中。 (3) 判斷功能:能夠對輸入的表示式判斷其正確與否,如果表示式不正確則無法進行運算;表示式正確的情況下執行運算功能。 (4) 運算功能:可以實現大整數的加法、減法、乘法和除法運算。
  2. 擴充套件要求 (1) 實現一些常用的數學函式對大整數進行運算,如:大整數的平方根運算sqrt(x)、大整數的冪運算pow(x,y)等。 【其他要求】 (1)變數、函式命名符合規範。 (2)註釋詳細:每個變數都要求有註釋說明用途;函式有註釋說明功能,對引數、返回值也要以註釋的形式說明用途;關鍵的語句段要求有註釋解釋。 (3)程式的層次清晰,可讀性強。 (4)介面美觀,互動方便。

實現該問題的難度主要是在除法,加減乘皆可將大整數轉化為字串,然後進行相應的運算,除法我是用的是之前在LeetCode刷題時遇到的一個題目,20.兩數相除這個題目的啟發,點選傳送門 可以看看我之前總結的在不使用除法以及取餘的情況下如何進行除法運算。關於擴充套件要求我目前還未新增,新增之後我會重新修改這篇博文的!,實現的程式碼格式。(程式碼比較長,可以點選傳送門進GitHub直接下載整個作業原始碼) 執行介面比較簡單,示例如下:

手動輸入 在這裡插入圖片描述

從檔案中讀取 在這裡插入圖片描述

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BigNum {

    public static void main(String[] args) throws IOException {
        while (true) {
            Scanner sc = new Scanner(System.in);
            System.out.println("--------------------\n請選擇方式:");
            System.out.println("1.手動輸入\n2.從檔案讀取\n0.退出系統\n--------------------");
            String choice = sc.nextLine();
            switch (choice) {
                case "1":
                    arithmetic();
                    break;
                case "2":
                    arithmeticByFile();
                    break;
                case "0":
                    break;
                default:
                    System.out.println("非法輸入,請重試!");
            }
            if (choice.equals("0")) {
                break;
            }
        }

    }


    /**
     * 手動輸入
     */
    private static void arithmetic() {
        while (true) {
            System.out.println("\n\n--------------------\n請選擇要執行的運算:");
            System.out.println("1.加法");
            System.out.println("2.減法");
            System.out.println("3.乘法");
            System.out.println("4.除法");
            System.out.println("0.退出\n--------------------");
            Scanner sc = new Scanner(System.in);
            String choice = sc.nextLine();
            switch (choice) {
                case "1":
                    Scanner sc1 = new Scanner(System.in);
                    System.out.print("\n\n請輸入被加數:");
                    String a1 = sc1.nextLine();
                    System.out.print("請輸入加數:");
                    String b1 = sc1.nextLine();
                    if (checkNum(a1) && checkNum(b1)) {
                        String num1 = add(a1, b1);
                        System.out.println(mergeStr(a1, b1, choice, num1));
                    } else {
                        System.out.println("數字格式有誤,請檢查");
                    }
                    break;
                case "2":
                    Scanner sc2 = new Scanner(System.in);
                    System.out.print("\n\n請輸入被減數:");
                    String a2 = sc2.nextLine();
                    System.out.print("請輸入減數:");
                    String b2 = sc2.nextLine();
                    if (checkNum(a2) && checkNum(b2)) {
                        String num2 = subtract(a2, b2);
                        System.out.println(mergeStr(a2, b2, choice, num2));
                    } else {
                        System.out.println("數字格式有誤,請檢查");
                    }
                    break;
                case "3":
                    Scanner sc3 = new Scanner(System.in);
                    System.out.print("\n\n請輸入被乘數:");
                    String a3 = sc3.nextLine();
                    System.out.print("請輸入乘數:");
                    String b3 = sc3.nextLine();
                    if (checkNum(a3) && checkNum(b3)) {
                        String num3 = mul(a3, b3);
                        System.out.println(mergeStr(a3, b3, choice, num3));
                    } else {
                        System.out.println("數字格式有誤,請檢查");
                    }
                    break;
                case "4":
                    Scanner sc4 = new Scanner(System.in);
                    System.out.print("\n\n請輸入被除數:");
                    String a4 = sc4.nextLine();
                    System.out.print("請輸入除數:");
                    String b4 = sc4.nextLine();
                    if (checkNum(a4) && checkNum(b4)) {
                        String num4 = division(a4, b4);
                        System.out.println(mergeStr(a4, b4, choice, num4));
                    } else {
                        System.out.println("數字格式有誤,請檢查");
                    }
                    break;
                case "0":
                    break;
                default:
                    System.out.println("非法輸入,請重試!");
            }
            if (choice.equals("0")) {
                break;
            }
        }
    }


    /**
     * 以檔案的形式來計算
     */
    private static void arithmeticByFile() {
        String str = "";
        try {
            str = readFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<String> list = checkFileStr(str);
        if (list.size() == 0) {
            System.out.println("字串匹配時有誤,請檢查");
        } else {
            String num = "";
            String num1 = list.get(0);
            String sign = list.get(1);
            String num2 = list.get(2);
            if (!checkNum(num1) || !checkNum(num2)) {
                System.out.println("數字格式有誤,請檢查");
                return;
            }
            switch (sign) {
                case "+":
                    num = add(num1, num2);
                    break;
                case "-":
                    num = subtract(num1, num2);
                    break;
                case "*":
                    num = mul(num1, num2);
                    break;
                case "/":
                    num = division(num1, num2);
                default:
                    System.out.println("運算子有誤,請檢查");
                    return;
            }
            try {
                writeFile(str + " = " + num);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 檢查檔案中字串是否合法
     *
     * @param str 需要檢查的字串
     * @return 是否合法
     */
    private static List<String> checkFileStr(String str) {
        String pattern = "\\((-?[\\d+])\\)(\\W)\\((-?[\\d+])\\)";
        List<String> list = new ArrayList<>();

        // 建立 Pattern 物件
        Pattern r = Pattern.compile(pattern);

        // 現在建立 matcher 物件
        Matcher m = r.matcher(str);
        if (m.find()) {
            list.add(m.group(1));
            list.add(m.group(2));
            list.add(m.group(3));
        }
        return list;
    }


    /**
     * 檢查輸入的數字是否合法
     *
     * @param str 需要檢查的字串
     * @return 是否合法
     */
    private static boolean checkNum(String str) {
        String pattern = "^-?\\d+$";

        // 建立 Pattern 物件
        Pattern r = Pattern.compile(pattern);

        // 現在建立 matcher 物件
        Matcher m = r.matcher(str);

        return m.find() && m.group(0).equals(str);
    }


    /**
     * 讀檔案
     *
     * @return 若檔案不存在則返回空,正常則返回檔案中字串
     */
    private static String readFile() throws IOException {
        File file = new File("file/arithmetic.txt");
        if (file.exists()) {
            FileInputStream fileInputStream = new FileInputStream(file);
            InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8");
            BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
            String line = bufferedReader.readLine();
            bufferedReader.close();
            inputStreamReader.close();
            fileInputStream.close();
            System.out.println("\n\n獲取到的算式為: " + line);
            return line;
        } else {
            return "";
        }
    }


    /**
     * 寫檔案
     *
     * @param result 計算結果
     */
    private static void writeFile(String result) throws IOException {
        File file = new File("file/result.txt");
        if (file.exists()) {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(fileOutputStream, "UTF-8");
            BufferedWriter bufferedWriter = new BufferedWriter(outputStreamWriter);
            bufferedWriter.write(result);
            bufferedWriter.close();
            outputStreamWriter.close();
            fileOutputStream.close();
            System.out.println("計算結果為: " + result + "\n\n");
        } else {
            System.out.println("檔案不存在");
        }
    }


    /**
     * 合併字串
     *
     * @param num1 數1
     * @param num2 數2
     * @param sign 運算子
     * @param num  結果
     * @return 合併後的字串
     */
    private static String mergeStr(String num1, String num2, String sign, String num) {
        switch (sign) {
            case "1":
                sign = "+";
                break;
            case "2":
                sign = "-";
                break;
            case "3":
                sign = "*";
                break;
            case "4":
                sign = "/";
                break;
        }
        return "\n答案為:" + num1 + " " + sign + " " + num2 + " = " + num;
    }


    /**
     * 大整數的加法
     *
     * @param a 被加數
     * @param b 加數
     * @return 和
     */
    private static String add(String a, String b) {
        boolean plus = true;
        if (a.charAt(0) == '-' && b.charAt(0) != '-') {
            return subtract(b, a.replace("-", ""));
        } else if (a.charAt(0) !=