/**
 * Fractions with integer numerators and denominators.  Once
 * the value of a fraction has been set, that value should
 * not be changed.
 *
 * @author Samuel A. Rebelsky
 * @author Fillip Fictitious
 * @author Fiona Fictitious
 * @version 1.0 of February 2000
 */
public class Fraction
{
  // +--------+--------------------------------------------------
  // | Fields |
  // +--------+

  /** The numerator of the fraction.  Can be positive or negative. */
  protected int num;

  /** The denominator of the fraction.  Should be positive. */
  protected int denom;

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

  /**
   * Build a new fraction with value A/B.
   */
  public Fraction(int A, int B)
  {
    this.num = A;
    this.denom = B;
    this.cleanup();
  } // Fraction(int,int)

  // +------------+----------------------------------------------
  // | Extractors |
  // +------------+

  /** Get the numerator of the fraction. */
  public int getNumerator() {
    return this.num;
  } // getNumerator()

  /** Get the denominator of the fraction. */
  public int getDenominator() {
    return this.denom;
  } // getDenominator()

  /** Return the fraction as a string. */
  public String toString() {
    return this.num + "/" + this.denom;
  } // toString()

  // +-------------------------+---------------------------------
  // | Mathematical Operations |
  // +-------------------------+

  /** 
   * Add this fraction to another fraction, creating a third
   * fraction for the result.
   */
  public Fraction add(Fraction other) {
    // A/B + C/D = (AD + BC)/BD
    int num = this.num*other.denom + other.num*this.denom;
    int denom = other.denom*this.denom;
    return new Fraction(num,denom);
  } // add(Fraction)

  /**
   * Multiply this fraction by another fraction, creating
   * a new fraction.
   */
  public Fraction multiply(Fraction other) {
    // A/B * C/D = (A*C)/(B*D)
    return new Fraction(this.num*other.num,
                        this.denom*other.denom);
  } // multiply(Fraction)

  /**
   * Divide this fraction by another fraction, creating
   * a new fraction.
   */
  public Fraction divide(Fraction other) {
    // A/B / C/D = A/B * 1/(C/D) = A/B * D/C = (AD)/(BC)
    return new Fraction(this.num*other.denom,
                        this.denom*other.num);
  } // divide(Fraction);

  /**
   * Negate this fraction, creating a new fraction.
   */
  public Fraction negate()
  {
    // -(A/B) = (-A)/B
    return new Fraction(-this.num, this.denom);
  } // negate()

  /**
   * Subtract another fraction from this fraction, creating
   * a new fraction for the result.
   */
  public Fraction subtract(Fraction other)
  {
    return add(other.negate());
  } // subtract(Fraction)


  // +-----------+-----------------------------------------------
  // | Modifiers |
  // +-----------+

  // This class has no modifiers.

  // +---------+-------------------------------------------------
  // | Helpers |
  // +---------+

  /** 
   * "Clean up" the fraction to ensure that the numerator and
   * denominator meet the appropriate standards.
   */
  protected void cleanup()
  {
    // If the denominator is negative, multiply both parts
    // by -1 to make it positive without changing the value
    // of the fraction.
    if (this.denom < 0) {
      this.denom = -this.denom;
      this.num = -this.num;
    }
  } // cleanup()

} // class Fraction


