/**
�* @author Shiang-Yun Yang
�*/
public class Rational {
private int numerator;
private int denominator;
private boolean simplify = false;
/**
�����* Initializes the class to 0/1.
�����*/
public Rational() {
this(0, 1);
}
/**
�����* @param wholeNumber
�����* Initializes the class to wholeNumber/1.
�����*/
public Rational(int wholeNumber) {
this(wholeNumber, 1);
}
/**
�����* Initializes the class to theNum/theDen.
�����*
�����* @param theNum
�����* assign this.numerator
�����* @param theDen
�����* assign this.denominator
�����*/
public Rational(int theNum, int theDen) {
numerator = theNum;
denominator = theDen;
simplify();
}
/*
�����* It's a copy constructor. It can't use
�����* "this(val.numerator, val.denomiator)" after "if". Because
�����* "Constructor call must be the first statement in a constructor"
�����*/
public Rational(Rational val) {
if (val == null) {
System.out.println("Exception : Null Pointer.");
System.exit(0);
}
numerator = val.numerator;
denominator = val.denominator;
simplify();
}
/*
�����* The following method will use "checkSimple()" to avoid "overflow".
�����*/
/**
�����* @return a Rational with val1 + val2
�����*/
public static Rational add(Rational val1, Rational val2) {
checkSimple(val1);
checkSimple(val2);
int newNum, newDen;
newDen = val1.denominator / gcd(val1.denominator, val2.denominator)
* val2.denominator;
newNum = val1.numerator * (newDen / val1.denominator) + val2.numerator
* (newDen / val2.denominator);
return new Rational(newNum, newDen);
}
/**
�����* @return a Rational with val1 - val2
�����*/
public static Rational subtract(Rational val1, Rational val2) {
checkSimple(val1);
checkSimple(val2);
int newNum, newDen;
newDen = val1.denominator / gcd(val1.denominator, val2.denominator)
* val2.denominator;
newNum = val1.numerator * (newDen / val1.denominator) - val2.numerator
* (newDen / val2.denominator);
return new Rational(newNum, newDen);
}
/**
�����* @return a Rational with val1 * val2
�����*/
public static Rational multiply(Rational val1, Rational val2) {
checkSimple(val1);
checkSimple(val2);
int newNum, newDen;
newNum = val1.numerator * val2.numerator;
newDen = val1.denominator * val2.denominator;
return new Rational(newNum, newDen);
}
/**
�����* @return a Rational with val1 / val2
�����*/
public static Rational divide(Rational val1, Rational val2) {
checkSimple(val1);
checkSimple(val2);
int newNum, newDen;
newNum = val1.numerator * val2.denominator;
newDen = val1.denominator * val2.numerator;
return new Rational(newNum, newDen);
}
/**
�����* Returns a Rational whose value is (this + val).
�����*
�����* @param val
�����* value to be added to this Rational.
�����* @return this + val
�����*/
public Rational add(Rational val) {
return Rational.add(this, val);
}
/**
�����* Returns a Rational whose value is (this - val).
�����*
�����* @param val
�����* value to be subtracted to this Rational.
�����* @return this - val
�����*/
public Rational subtract(Rational val) {
return Rational.subtract(this, val);
}
/**
�����* Returns a Rational whose value is (this * val).
�����*
�����* @param val
�����* value to be multiplied by this Rational.
�����* @return this * val
�����*/
public Rational multiply(Rational val) {
return Rational.multiply(this, val);
}
/**
�����* Returns a Rational whose value is (this / val).
�����*
�����* @param val
�����* value by which this Rational is to be divided.
�����* @return this / val
�����*/
public Rational divide(Rational val) {
return Rational.divide(this, val);
}
/**
�����* Returns a int whose value is the greatest common divisor of abs(x) and
�����* abs(y). Returns 0 if x==0 && y==0.
�����*
�����* @return GCD(abs(x), abs(y))
�����*/
public static int gcd(int x, int y) {
x = Math.abs(x);
y = Math.abs(y);
if (y == 0)
return x;
int tmp;
while (x % y != 0) {
tmp = x;
x = y;
y = tmp % y;
}
return y;
}
/**
�����* Converts the rational number to simplified form.
�����*/
private void simplify() {
if (denominator == 0) {
System.out.println("Exception : / by zero.");
System.exit(0);
}
int GCD = gcd(numerator, denominator);
numerator /= GCD;
denominator /= GCD;
if (denominator < 0) {
numerator *= -1;
denominator *= -1;
}
simplify = true;
}
public int getNumerator() {
checkSimple(this);
return this.numerator;
}
public int getDenominator() {
checkSimple(this);
return this.denominator;
}
/*
�����* It can't use simplify() method after Mutator method because it will have
�����* logic error.
�����*/
public void set(int newNum, int newDen) {
if (newDen == 0) {
System.out.println("Exception : / by zero.");
System.exit(0);
}
this.numerator = newNum;
this.denominator = newDen;
simplify = false;
}
public void set(Rational val) {
this.set(val.numerator, val.denominator);
}
public void setNumerator(int newNum) {
this.set(newNum, this.denominator);
}
public void setDenominator(int newDen) {
this.set(this.numerator, newDen);
}
public String toString() {
checkSimple(this);
return numerator + "/" + denominator;
}
public double toDouble() {
checkSimple(this);
return (double) numerator / denominator;
}
public static void checkSimple(Rational val) {
if (val.simplify == false)
val.simplify();
}
/*
�����* I don't use public boolean equals(Rational x), because if you use Object
�����* x = new Rational(5, 6); Rational y = new Rational(5, 6); then
�����* x.equals(y), this way will get "false". Equals must be Reflexive,
�����* Symmetric and Transitive.
�����*/
@Override
public boolean equals(Object x) {
if (!(x instanceof Rational)) {
return false;
}
checkSimple(this);
checkSimple((Rational) x);
return numerator == ((Rational) x).numerator
&& denominator == ((Rational) x).denominator;
}
}
文章定位: