/** * Rational numbers (those that can be expressed as the ratio of two * integers). * * @author Samuel A. Rebelsky * @author Yvonne Palm * @author Alex Leach * @author Evan Case * @author Jonathan Wellons */ public class Rational implements Multipliable { // +--------+---------------------------------------------- // | Fields | // +--------+ /** The numerator of the number. */ private long numerator; /** The denominator of the number. */ private long denominator; // +--------------+---------------------------------------- // | Constructors | // +--------------+ /** Convert a MyInteger to a rational. */ public Rational(MyInteger mint) { this(mint.toString()); } // Rational(MyInteger) /** Convert a string of the form "n/d" or just "n" to a rational. */ public Rational(String str) { int pos = str.indexOf('/'); if (pos == -1) { this.numerator = Long.parseLong(str); this.denominator = 1; } else { this.numerator = Long.parseLong(str.substring(0, pos)); this.denominator = Long.parseLong(str.substring(pos+1)); this.simplify(); } } // Rational(String) /** Create the rational number num/denom. */ public Rational(long num, long denom) { this.numerator = num; this.denominator = denom; this.simplify(); } // Rational(long,long) public Rational(float num) { double n = num; long d = 1; // As long as there is a fractional part while (n - Math.floor(n) > 0) { // Increment both n and d by the same factor n = n * 2; d = d * 2; } this.numerator = (long) n; this.denominator = d; this.simplify(); } // Rational(float) // +------------------+------------------------------------ // | Exported Methods | // +------------------+ /** Multiply by another multipliable value. */ public Multipliable multiply(Multipliable other) { if (other instanceof Rational) { Rational r = (Rational) other; return new Rational(this.numerator * r.numerator, this.denominator * r.denominator); } else if (other instanceof MyInteger) { MyInteger mint = (MyInteger) other; return new Rational(this.numerator * mint.value, this.denominator); } else { return new Rational(0); } } // multiply(Multipliable) /** Convert this rational number to a double. */ public double doubleValue() { return ((double) this.numerator) / this.denominator; } // doubleValue(); /** Convert this rational number to a string of the form num/denom. */ public String toString() { return this.numerator + "/" + this.denominator; } // toString() // +-----------------+------------------------------------- // | Private Methods | // +-----------------+ /** * Simplify the rational, so that gcd(numerator,denominator) = 1. */ private void simplify() { // Find the greatest common divisor of the numerator and denom. long gcd = Rational.greatestCommonDivisor(this.numerator, this.denominator); // Divide both numerator and denominator by that value. this.numerator = this.numerator / gcd; this.denominator = this.denominator / gcd; } // simplify() // +---------------+--------------------------------------- // | Class Methods | // +---------------+ /** Divide a by b. */ public static Rational divide(Rational a, Rational b) { return new Rational(0,1); // STUB } // divide(Rational,Rational) /** Multiply a by b. */ public static Rational multiply(Rational a, Rational b) { return new Rational(a.numerator * b.numerator, a.denominator * b.denominator); } // multiply(Rational,Rational) // +-----------------------+------------------------------- // | Private Class Methods | // +-----------------------+ /** Find the greatest common divisor of x and y. */ private static long greatestCommonDivisor(long x, long y) { // If y is 0, the gcd is x. if (y == 0) return x; // If y is 1, the gcd is 1. if (y == 1) return 1; // Euclid said: gcd(x,y) = gcd(y, x mod y) return greatestCommonDivisor(y, x % y); } // greatestCommonDivisor(int, int) } // class Rational