解答例 - j2.lesson06.Rational

package j2.lesson06;

/**
 * 課題1904 - 解答例.
 * 分数を表すクラス.
 @author arakawa
 @version $Id: Rational_java.rps,v 1.1 2006/03/06 12:56:15 java2005 Exp $
 */
public class Rational extends Number {

    /** serial version UID. */
    private static final long serialVersionUID = 1L;

    /** 分子. */
    private final int numerator;

    /** 分母. */
    private final int denominator;

    /**
     * 分数インスタンスを生成する。
     @param numerator 分子
     @param denominator 分母
     */
    public Rational(int numerator, int denominator) {
        super();
        if (numerator == 0) {
            this.numerator = 0;
            this.denominator = 1;
        }
        else {
            int m = numerator;
            int n = denominator;
            int sign = 1;
            if (m < 0) {
                sign = -sign;
                m = -m;
            }
            if (n < 0) {
                sign = -sign;
                n = -n;
            }
            int gcd = gcd(m, n);
            this.numerator = sign * m / gcd;
            this.denominator = n / gcd;
        }
    }

    /**
     * 引数で与えられた2つの整数の最大公約数を返す。
     <code>m, n</code> が負の値であった場合は考慮しなくて良い。
     <code>m, n</code> の最大公約数を求めるアルゴリズム <code>gcd(m,n)</code> は次のように表せる。
     
     <pre>
     *   gcd(m,0) = m
     *   gcd(m,n) = gcd(n, (mをnで割った余り)) (n != 0)
     </pre>
     
     @param m 整数1
     @param n 整数2
     @return 引数で与えられた2つの整数の最大公約数
     */
    private static int gcd(int m, int n) {
        if (n == 0) {
            return m;
        }
        else {
            return gcd(n, m % n);
        }
    }

    /**
     * この分数と他の分数を加算した結果を表す、新しい分数を返す。
     * この操作によってもとの分数が変更されることはない。
     @param r 加算する値
     @return 2つの分数を加算した結果の新しい分数
     */
    public Rational add(Rational r) {
        int num = this.numerator * r.denominator + r.numerator * this.denominator;
        int den = this.denominator * r.denominator;
        return new Rational(num, den);
    }

    /**
     * この分数から他の分数を減算した結果を表す、新しい分数を返す。
     * この操作によってもとの分数が変更されることはない。
     @param r 減算する値
     @return 2つの分数を減算した結果の新しい分数
     */
    public Rational sub(Rational r) {
        int num = this.numerator * r.denominator - r.numerator * this.denominator;
        int den = this.denominator * r.denominator;
        return new Rational(num, den);
    }

    /**
     * この分数と他の分数を乗算した結果を表す、新しい分数を返す。
     * この操作によってもとの分数が変更されることはない。
     @param r 乗算する値
     @return 2つの分数の積
     */
    public Rational multiply(Rational r) {
        int num = this.numerator * r.numerator;
        int den = this.denominator * r.denominator;
        return new Rational(num, den);
    }

    /**
     * この分数から他の分数を割った商を表す、新しい分数を返す。
     * この操作によってもとの分数が変更されることはない。
     @param r 割る値
     @return 2つの分数の商
     */
    public Rational divide(Rational r) {
        int num = this.numerator * r.denominator;
        int den = this.denominator * r.numerator;
        return new Rational(num, den);
    }

    /**
     * この分数を <code>int</code> 型で表した値を返す。
     <code>int</code> 型で表せない範囲は切り捨てられる。
     @return この分数を <code>int</code> 型で表した値
     */
    public int intValue() {
        return this.numerator / this.denominator;
    }

    /**
     * この分数を <code>long</code> 型で表した値を返す。
     <code>intValue()</code> と同じ値を返す。
     @return <code>return intValue()</code>
     @see #intValue()
     */
    public long longValue() {
        return this.intValue();
    }

    /**
     * この分数を <code>float</code> 型で表した値を返す。
     <code>(float) doubleValue()</code>と同じ値を返す。
     @return <code>return (float) doubleValue()</code>
     @see #doubleValue()
     */
    public float floatValue() {
        return (floatthis.doubleValue();
    }

    /**
     * この分数を <code>double</code> 型で表した値を返す。
     <code>double</code>型で表せない範囲は切り捨てられる。
     <code>int</code> 型の値を <code>double</code> 型に変更するには、
     <code>(double) int型の値</code> とすればよい。
     @return この分数を <code>double</code> 型で表した値
     */
    public double doubleValue() {
        return (doublethis.numerator / this.denominator;
    }
    
    /**
     * この分数を既約分数として文字列に変換する。
     * 表示形式は <code>(分子) + &quot;/&quot; + (分母)</code>
     * 既約分数であるので、<code>new Rational(3, 6).toString()</code> は&quot;1/2&quot;を返す必要がある。
     * 分子が<code>0</code>の場合は必ず<code>&quot;0/1&quot;</code>を返す。
     * 約分によって分母が<code>1</code>になった場合も、分母は表示する。
     * 分母の値は必ず正の値である必要がある。
     @return この分数の文字列表現
     */
    public String toString() {
        return this.numerator + "/" this.denominator;
    }
}