構造有理數~

南郭竽發表於2018-06-10

在程式設計中,資料型別基本會有數字型別,有的還會細分整數和小數,但是一般不會區分有理數與無理數。辣麼,如何打造一個有理數型別呢?

什麼是有理數型別?首先有理數就是分數。其次,有理數既然是一種資料結構,就有建立和操作的方法。

——————— 啟發與 sicp ——————-

其實實現語言不重要,這裡表達的是一種抽象分層的思想。(假裝有)

java 實現:

package com.pycat.simple.ration;

import javafx.util.Pair;

/**
 * Created by cat on 2018/6/10.
 * 有理數
 */
public class Ration<K, V> extends Pair<K, V> {


    /**
     * Creates a new pair
     *
     * @param key   The key for this pair
     * @param value The value to use for this pair
     */
    Ration(K key, V value) {
        super(key, value);
    }

    @Override
    public String toString() {
        if (getValue() instanceof Integer) {
            int v = (Integer) getValue();
            return v == 1
                    ? String.format("Ration(%s)", getKey())
                    : String.format("Ration(%s/%s)", getKey(), getValue());
        } else if (getKey() == getValue()) {
            return String.format("Ration(%s)", 1);
        }
        return String.format("Ration(%s/%s)", getKey(), getValue());
    }
}
package com.pycat.simple.ration;

import com.pycat.simple.ration.Ration;

/**
 * Created by cat on 2018/6/10.
 * 有理數操作
 */
public class RationOperator {

    private RationOperator() {
    }

    public static Ration<Integer, Integer> makeRation(int n, int d) {
        if (d == 0) throw new ArithmeticException("denomination can't be zero.");
        return new Ration<>(n / gcd(n, d), d / gcd(n, d));
    }

    public static int getNumber(Ration<Integer, Integer> ration) {
        return ration.getKey();
    }


    public static int getDenominate(Ration<Integer, Integer> ration) {
        return ration.getValue();
    }

    /**
     * 有理數相加
     *
     * @param x ration
     * @param y ration
     * @return x + y (其中 x,y 都是有理數)
     */
    public static Ration<Integer, Integer> add(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {

        int n = x.getKey() * y.getValue() + x.getValue() * y.getKey();
        int d = x.getValue() * y.getValue();

        return makeRation(n, d);
    }

    /**
     * 有理數相減
     *
     * @param x ration
     * @param y ration
     * @return x - y (其中 x,y 都是有理數)
     */
    public static Ration<Integer, Integer> minus(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {

        int n = x.getKey() * y.getValue() - x.getValue() * y.getKey();
        int d = x.getValue() * y.getValue();

        return makeRation(n, d);
    }

    /**
     * 有理數相乘
     *
     * @param x ration
     * @param y ration
     * @return x * y (其中 x,y 都是有理數)
     */
    public static Ration<Integer, Integer> multi(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {
        int n = x.getKey() * y.getKey();
        int d = x.getValue() * y.getValue();
        return makeRation(n, d);
    }

    /**
     * 有理數相除
     *
     * @param x ration
     * @param y ration
     * @return x / y (其中 x,y 都是有理數)
     */
    public static Ration<Integer, Integer> divide(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {

        return multi(x, makeRation(y.getValue(), y.getKey()));
    }


    /**
     *
     * 第一步:任意給定兩個正整數;判斷它們是否都是偶數。若是,則用2約簡;若不是則執行第二步。
     * 第二步:以較大的數減較小的數,接著把所得的差與較小的數比較,並以大數減小數。繼續這個操作,直到所得的減數和差相等為止。
     * 則第一步中約掉的若干個2與第二步中等數的乘積就是所求的最大公約數。
     * 其中所說的“等數”,就是最大公約數。求“等數”的辦法是“更相減損”法。所以更相減損法也叫等值演算法。
     *
     * @param n
     * @param d
     * @return
     */
    private static int gcd(int n, int d) {
        int before = 1;
        while (n % 2 == 0 && d % 2 == 0) {
            n = n / 2;
            d = d / 2;
            before *= 2;
        }
        int r = 0;
        int max;
        int min;
        max = Math.max(n, d);
        min = Math.min(n, d);
        n = max;
        d = min;
        while (r != d) {
            r = n - d;
            n = Math.max(r, d);
            d = Math.min(r, d);

            max = Math.max(n, d);
            min = Math.min(n, d);
            n = max;
            d = min;
        }
        return r * before;
    }

    public static void main(String[] args) {
//        System.out.println(gcd(6, 8));

        Ration<Integer, Integer> a = RationOperator.makeRation(1, 2);
        Ration<Integer, Integer> b = RationOperator.makeRation(1, 4);
        System.out.println(String.format("%s + %s = %s", a, b, RationOperator.add(a, b)));
        System.out.println(String.format("%s - %s = %s", a, b, RationOperator.minus(a, b)));
        System.out.println(String.format("%s * %s = %s", a, b, RationOperator.multi(a, b)));
        System.out.println(String.format("%s / %s = %s", a, b, RationOperator.divide(a, b)));
    }
}

相關文章