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; } } } }