一個分數類的實現——Rational類

Renaway發表於2018-02-15

分數是我們從小學就開始接觸的一類有理數,但是在計算機中只有浮點型資料。我們今天(除夕)就來實現一個分數類,以見證這歷史性的時刻。

從最基礎的分數結構來思考,我們需要一個分子分母,比如這樣:

public class Rational {
    private int num;  /* The numerator of this Rational */
    private int den;  /*  The denominator of this Rational */
    public Rational(int x, int y) {
       num = x;
       den = y;
    }
}

我們一開始很容易這樣寫,但這樣寫是有很大問題的。例如算術運算規則對分子和分母的值有限制,這裡面最明顯的限制就是分母不能為0。構造器應該檢查這種情況並在分母為0時丟擲異常。還有,這樣的分數不是最簡形式,我們會有很多種不同的方式來表示同一個有理數。比如三分之一:

1/3     2/6    100/300     -1/-3  ...


要處理這些問題,我們先遵循數學家們給的規則:

1.分數總是表示為最簡形式,分子分母要同時處理它們的最大公約數。可以使用gcd方法求分子分母的最大公約數。

2.分母總是整數,也就是分數值是和分子一起儲存的。

3.有理數0總是表示為分數0/1。

這樣我們就比較容易地寫出分數類的構造器了!當然,我們還可能需要傳一個分母為1的假分數,這時直接把分子傳給一個引數的構造器就行,我們用this關鍵字呼叫已經寫好的構造器。

我們還要給分數器增加算術運算的方法以及通用的toString方法,所以程式碼的一種可能實現為:

public class Rational {
	
	private int num;
	private int den;
	
	public Rational() {
		this(0);
	}
	
	public Rational(int n) {
		this(n, 1);
	}
	
	public Rational(int x, int y) {
		if (y == 0) throw new RuntimeException("Division by zero");
		if (x == 0) {
			num = 0;
			den = 1;
		} else {
			int g = gcd(Math.abs(x), Math.abs(y));
			num = x / g;
			den = Math.abs(y) / g;
			if (y < 0) num = -num;
		}
	}
	
	public Rational add(Rational r2) {
		return new Rational(this.num * r2.den + r2.num * this.den, this.den * r2.den);
	}
	
	public Rational substract(Rational r2) {
		return new Rational(this.num * r2.den - r2.num * this.den, this.den * r2.den);
	}
	
	public Rational multiply(Rational r2) {
		return new Rational(this.num * r2.num, this.den * r2.den);
	}
	
	public Rational divide(Rational r2) {
		return new Rational(this.num * r2.den, this.den * r2.num);
	}
	
	@Override
	public String toString() {
		if (den == 1)
			return "" + num;
		return num + "/" + den;
	}
	
	private int gcd(int x, int y) {
		int r = x % y;
		while (r != 0) {
			x = y;
			y = r;
			r = x % y;
		}
		return y;
	}
	
	
}

放爆竹的時光一去不復還,這個類設計地真好,不得不從書上借鑑過來!

相關文章