/**
 * A simple (and partial) implementation of fractions.
 * 
 * @author Samuel A. Rebelsky
 * @author Your Name Here
 * @version 1.0 of February 1999
 */
public class Fraction {
  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /** The numerator. */
  protected long num;
  /** The denominator. */
  protected long denom;


  // +--------------+--------------------------------------------
  // | Constructors |
  // +--------------+

  /**
   * Create the fraction a/b (simplifying if necessary).
   */
  public Fraction(long a, long b) {
    this.num = a;
    this.denom = b;
    this.simplify();
  } // Fraction(long,long)
 
  /**
   * Create the ``zero'' fraction (0/1 for convenience).
   */
  public Fraction() {
    this.num = 0;
    this.denom = 1;
  } // Fraction()

  /**
   * Create a ``whole'' fraction (the fraction corresponding
   * to an integer).
   */
  public Fraction(long val) {
    this.num = val;
    this.denom = 1;
  } // Fraction(long)


  // +------------------+----------------------------------------
  // | Standard Methods |
  // +------------------+

  /**
   * Determine if this fraction equals another fraction.
   */
  public boolean equals(Fraction other) {
    // A denominator of 0 is problematical.  If both are 0, we'll
    // assume that they're equal.
    if ((this.denom == 0) && (other.denom == 0)) {
      return true;
    }
    // If only one denominator is 0, we'll assume they're different.
    else if ((this.denom == 0) || (other.denom == 0)) {
      return false;
    }
    // a/b = c/d if a*d=b*c.  (There's some disadvantage to this
    // technique because a*c or b*d can overflow.)
    else {
      return (this.num*other.denom) == (other.num*this.denom);
    }
  } // equals(Fraction)

  /**
   * Determine if this fraction equals another object.
   */
  public boolean equals(Object other) {
    return (other instanceof Fraction) && (equals((Fraction) other));
  } // equals(Object)

  /**
   * Convert this fraction to a string.
   */
  public String toString() {
    // Special case: denominator is 0.  Return an error string.
    if (this.denom == 0) {
      return "Not a number";
    }
    // Special case: denominator is 1.  Return just the numerator.
    else if (this.denom == 1) {
      return Long.toString(this.num);
    }
    // Normal case.  Return the fraction in the form a/b.
    else  {
      return (this.num + "/" + this.denom);
    }
  } // toString()


  // +--------------------+--------------------------------------
  // | Additional Methods |
  // +--------------------+

  /**
   * Compute the fraction that results from adding this fraction
   * to another fraction.
   *
   * a/b + c/d = (a*d + b*c)/(b*d)
   */
  public Fraction add(Fraction other) {
    return new Fraction(
      this.num*other.denom + other.num*this.denom,
      this.denom*other.denom);
  } // add(Fraction)
   
  /**
   * Compute the fraction that results from dividing this
   * fraction by another fraction.
   *
   * (a/b)/(c/d) = a/b * d/c = (a*d)/(b*c)
   */
  public Fraction divide(Fraction other) {
    return new Fraction(
      this.num*other.denom,
      this.denom*other.num);
  } // divide(Fraction)

  /**
   * Compute the fraction that results from multiplying this
   * fraction by another fraction.
   *
   * a/b * c/d = (a*c)/(b*d)
   */
  public Fraction multiply(Fraction other) {
    return new Fraction(
      this.num*other.num,
      this.denom*other.denom);
  } // multiply(Fraction)

  /**
   * Compute the fraction that results from subtracting another
   * fraction from this fraction.
   *
   * a/b - c/d = (a*d - b*c)/(b*d)
   */
  public Fraction subtract(Fraction other) {
    return new Fraction(
      this.num*other.denom - other.num*this.denom,
      this.denom*other.denom);
  } // subtract(Fraction)


  // +----------------+------------------------------------------
  // | Helper Methods |
  // +----------------+

  /**
   * Compute the greatest common divisor of nonnegative integers
   * a and b.  May be useful in simplifying a fraction.  Uses a 
   * legendary algorithm.  Untested.
   */
  protected int gcd(int a, int b) {
    // Special case, required by the algorithm.  If b is 0, then
    // return a.
    if (b == 0) { return a; }
    // Other case.
    else { return gcd(b, a%b); }
  } // gcd(int,int)

  /**
   * Simplify the current fraction.  Currently unimplemented.
   */
  protected void simplify() {
  } // simplify()

} // class Fraction

