2012-04-09 07:35:18Morris

[JAVA][作業][Lab3] Rational.java

/**
* @author Shiang-Yun Yang
�*/
public class Rational {
    private int numerator;
    private int denominator;
    private boolean simplify = false;

    /**
�����* Initializes the class to 0/1.
�����*/
    public Rational() {
        this(0, 1);
    }

    /**
�����* @param wholeNumber
�����*            Initializes the class to wholeNumber/1.
�����*/
    public Rational(int wholeNumber) {
        this(wholeNumber, 1);
    }

    /**
�����* Initializes the class to theNum/theDen.
�����* 
�����* @param theNum
�����*            assign this.numerator
�����* @param theDen
�����*            assign this.denominator
�����*/
    public Rational(int theNum, int theDen) {
        numerator = theNum;
        denominator = theDen;
        simplify();
    }

    /*
�����* It's a copy constructor. It can't use
�����* "this(val.numerator, val.denomiator)" after "if". Because
�����* "Constructor call must be the first statement in a constructor"
�����*/
    public Rational(Rational val) {
        if (val == null) {
            System.out.println("Exception : Null Pointer.");
            System.exit(0);
        }
        numerator = val.numerator;
        denominator = val.denominator;
        simplify();
    }

    /*
�����* The following method will use "checkSimple()" to avoid "overflow".
�����*/
    /**
�����* @return a Rational with val1 + val2
�����*/
    public static Rational add(Rational val1, Rational val2) {
        checkSimple(val1);
        checkSimple(val2);
        int newNum, newDen;
        newDen = val1.denominator / gcd(val1.denominator, val2.denominator)
                * val2.denominator;
        newNum = val1.numerator * (newDen / val1.denominator) + val2.numerator
                * (newDen / val2.denominator);
        return new Rational(newNum, newDen);
    }

    /**
�����* @return a Rational with val1 - val2
�����*/
    public static Rational subtract(Rational val1, Rational val2) {
        checkSimple(val1);
        checkSimple(val2);
        int newNum, newDen;
        newDen = val1.denominator / gcd(val1.denominator, val2.denominator)
                * val2.denominator;
        newNum = val1.numerator * (newDen / val1.denominator) - val2.numerator
                * (newDen / val2.denominator);
        return new Rational(newNum, newDen);
    }

    /**
�����* @return a Rational with val1 * val2
�����*/
    public static Rational multiply(Rational val1, Rational val2) {
        checkSimple(val1);
        checkSimple(val2);
        int newNum, newDen;
        newNum = val1.numerator * val2.numerator;
        newDen = val1.denominator * val2.denominator;
        return new Rational(newNum, newDen);
    }

    /**
�����* @return a Rational with val1 / val2
�����*/
    public static Rational divide(Rational val1, Rational val2) {
        checkSimple(val1);
        checkSimple(val2);
        int newNum, newDen;
        newNum = val1.numerator * val2.denominator;
        newDen = val1.denominator * val2.numerator;
        return new Rational(newNum, newDen);
    }

    /**
�����* Returns a Rational whose value is (this + val).
�����* 
�����* @param val
�����*            value to be added to this Rational.
�����* @return this + val
�����*/
    public Rational add(Rational val) {
        return Rational.add(this, val);
    }

    /**
�����* Returns a Rational whose value is (this - val).
�����* 
�����* @param val
�����*            value to be subtracted to this Rational.
�����* @return this - val
�����*/
    public Rational subtract(Rational val) {
        return Rational.subtract(this, val);
    }

    /**
�����* Returns a Rational whose value is (this * val).
�����* 
�����* @param val
�����*            value to be multiplied by this Rational.
�����* @return this * val
�����*/
    public Rational multiply(Rational val) {
        return Rational.multiply(this, val);
    }

    /**
�����* Returns a Rational whose value is (this / val).
�����* 
�����* @param val
�����*            value by which this Rational is to be divided.
�����* @return this / val
�����*/
    public Rational divide(Rational val) {
        return Rational.divide(this, val);
    }

    /**
�����* Returns a int whose value is the greatest common divisor of abs(x) and
�����* abs(y). Returns 0 if x==0 && y==0.
�����* 
�����* @return GCD(abs(x), abs(y))
�����*/
    public static int gcd(int x, int y) {
        x = Math.abs(x);
        y = Math.abs(y);
        if (y == 0)
            return x;
        int tmp;
        while (x % y != 0) {
            tmp = x;
            x = y;
            y = tmp % y;
        }
        return y;
    }

    /**
�����* Converts the rational number to simplified form.
�����*/
    private void simplify() {
        if (denominator == 0) {
            System.out.println("Exception : / by zero.");
            System.exit(0);
        }
        int GCD = gcd(numerator, denominator);
        numerator /= GCD;
        denominator /= GCD;
        if (denominator < 0) {
            numerator *= -1;
            denominator *= -1;
        }
        simplify = true;
    }

    public int getNumerator() {
        checkSimple(this);
        return this.numerator;
    }

    public int getDenominator() {
        checkSimple(this);
        return this.denominator;
    }

    /*
�����* It can't use simplify() method after Mutator method because it will have
�����* logic error.
�����*/
    public void set(int newNum, int newDen) {
        if (newDen == 0) {
            System.out.println("Exception : / by zero.");
            System.exit(0);
        }
        this.numerator = newNum;
        this.denominator = newDen;
        simplify = false;
    }

    public void set(Rational val) {
        this.set(val.numerator, val.denominator);
    }

    public void setNumerator(int newNum) {
        this.set(newNum, this.denominator);
    }

    public void setDenominator(int newDen) {
        this.set(this.numerator, newDen);
    }

    public String toString() {
        checkSimple(this);
        return numerator + "/" + denominator;
    }

    public double toDouble() {
        checkSimple(this);
        return (double) numerator / denominator;
    }

    public static void checkSimple(Rational val) {
        if (val.simplify == false)
            val.simplify();
    }

    /*
�����* I don't use public boolean equals(Rational x), because if you use Object
�����* x = new Rational(5, 6); Rational y = new Rational(5, 6); then
�����* x.equals(y), this way will get "false". Equals must be Reflexive,
�����* Symmetric and Transitive.
�����*/
    @Override
    public boolean equals(Object x) {
        if (!(x instanceof Rational)) {
            return false;
        }
        checkSimple(this);
        checkSimple((Rational) x);
        return numerator == ((Rational) x).numerator
                && denominator == ((Rational) x).denominator;
    }
}