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 (float) this.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 (double) this.numerator / this.denominator;
}
/**
* この分数を既約分数として文字列に変換する。
* 表示形式は <code>(分子) + "/" + (分母)</code>。
* 既約分数であるので、<code>new Rational(3, 6).toString()</code> は"1/2"を返す必要がある。
* 分子が<code>0</code>の場合は必ず<code>"0/1"</code>を返す。
* 約分によって分母が<code>1</code>になった場合も、分母は表示する。
* 分母の値は必ず正の値である必要がある。
* @return この分数の文字列表現
*/
public String toString() {
return this.numerator + "/" + this.denominator;
}
}
|