import java.io.Serializable;
/**
* Instances of this class represent rational numbers.
* @author pearce
* @see Rational Numbers
*/
public class Rational implements Serializable, Comparable, Cloneable {
private static final long serialVersionUID = 1L;
private int numerator;
private int denominator;
/**
* Constructs the rational number
*
* numerator'/denominator'
*
* where
*
* numerator' = numerator/gcd
* denominator' = denominator/gcd
* gcd = greatest common divisor of numerator & denominator
*
* @param numerator the numerator of this rational
* @param denominator the denominator of this rational
* @throws Exception if denominator is <= 0
*/
public Rational(int numerator, int denominator) throws Exception {
if (denominator <= 0) {
throw new Exception("The denominator must be positive");
}
this.numerator = numerator;
this.denominator = denominator;
// remove common factors from numerator & denominator:
reduce();
}
/**
* Creates the rational number:
*
* numerator/1
*
* @param numerator numerator of this rational
* @throws An exception if denominator is 0 (which it won't be)
*/
public Rational(int numerator) throws Exception {
this(numerator, 1);
}
/**
* Creates the rational number
*
* 0/1
*
* @throws An exception if denominator is 0 (which it won't be)
*/
public Rational() throws Exception {
this(0);
}
/**
* @return the numerator
*/
public int getNumerator() {
return numerator;
}
/**
* @return the denominator
*/
public int getDenominator() {
return numerator;
}
/**
* @return the string representation of this rational
*/
public String toString() {
String result = "";
result += numerator;
result += '/';
result += denominator;
return result;
}
/**
* @param other any object
* @return true if other is a Rational
* with same numerator and denominator as this
*/
public boolean equals(Object other) {
if (other == null) return false;
Class otherClass = other.getClass();
Class thisClass = Rational.class;
if (!otherClass.equals(thisClass)) return false;
Rational otherRat = (Rational)other;
return otherRat.numerator == this.numerator
&&
otherRat.denominator == this.denominator;
}
public int hashCode() {
return this.toString().hashCode();
}
/**
* Compares this rational with some other rational
* @param other other Rational this Rational is being compared to
* @return > 0 if this > other, 0 if this == other, < 0 if this < other
*/
public int compareTo(Rational other) {
int term1 = this.getNumerator() * other.denominator;
int term2 = other.getNumerator() * this.denominator;
return term1 - term2;
}
/**
*
* @return shallow copy of this rational
* @throws CloneNotSupportedException
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* Converts this rational to a double
*
* @return numerator divided by denominator
*/
public double toDouble() {
return (double)numerator/(double)denominator;
}
/**
* Sums two rationals
* @param other other rational to add to this
* @return this + other
*/
public Rational add(Rational other) {
int newNum = this.numerator * other.numerator + other.numerator * this.denominator;
int newDen = this.denominator * other.denominator;
Rational result = null;
try {
result = new Rational(newNum, newDen);
} catch(Exception e) {
// should never get here
}
return result;
}
/**
* Multiplies two rationals
*
* @param other other rational to multiply
* @return other * this
*/
public Rational mul(Rational other) {
int newNum = this.numerator * other.numerator;
int newDen = this.denominator * other.denominator;
Rational result = null;
try {
result = new Rational(newNum, newDen);
} catch(Exception e) {
// should never get here
}
return result;
}
/**
* Removes common factors from numerator & denominator
*/
private void reduce() {
for(int i = 2; i <= Math.min(Math.abs(numerator), denominator); i++) {
while (numerator % i == 0 && denominator % i == 0) {
numerator /= i;
denominator /= i;
}
}
}
}