Block F


import java.math.BigInteger;
/**
 * This is a class of immutible extended-precision rational numbers.
 * It provides static constats for 0, 1, and 1/2.
 *
 */ 
public class BigFraction 
{
    /**
     * This is th BigFraction 0/1.
     */
    public static final BigFraction ZERO;
    /**
     * This is th BigFraction 1/1.
     */
    public static final BigFraction ONE;
    /**
     * This is th BigFraction 1/2.
     */
    public static final BigFraction HALF;

    static
    {
        ZERO = new BigFraction();
        ONE = BigFraction.valueOf(1,1);
        HALF = BigFraction.valueOf(1,1);
    }
    private final BigInteger num;
    private final BigInteger denom;  
    /**
     * This creats a BigFraction with a specified numerator
     * and denominator
     * @param num the numerator we are specifying for this BigFraction
     * @param denom the denominator we are specifying for this BigFraction
     * @throws IllegalArgumentException if a zero denominator is specified.
     */
    public BigFraction(BigInteger num, BigInteger denom)
    {
        if(denom.equals(BigInteger.ZERO))
        {
            throw new IllegalArgumentException();
        }
        if (denom.compareTo(BigInteger.ZERO) < 0)
        {
            num = num.negate();
            denom = denom.negate();
        }
        BigInteger d = num.gcd(denom);
        num = num.divide(d);
        denom = denom.divide(d);
        this.num = num;
        this.denom = denom;
    }
    /**
     * This creates the BigFraction 0/1, which is the same as BigFraction.ZERO.
     */
    public BigFraction()
    {
        this(BigInteger.ZERO, BigInteger.ONE);
    } 
    /**
     * This compares this BigFraction to the Object o for equality.
     * @param o the object we are comparing this BigFraction to
     * @return true if this BigFraction has the numerical value as o.
     */
    @Override
    public boolean equals(Object o)
    {
        //specie spicy meatball
        if(!(o instanceof BigFraction))
        {
            return false;
        }
        BigFraction that = (BigFraction)o;
        return num.equals(that.num) && denom.equals(that.denom);
    }
    /**
     * Creates a string representation of the form numerator/denominator.
     * @return numerator/denominator in a String.
     */
    @Override
    public String toString()
    {
        return String.format("%s/%s", num, denom);
    }
    /**
     * This calculates this + that.
     * @param that the BigFraction we are adding to this BigFraction
     * @return this + that
     */
    public BigFraction add(BigFraction that)
    {
        BigInteger top = num.multiply(that.denom).add(denom.multiply(that.num)); 
        BigInteger bottom = denom.multiply(that.denom);
        return new BigFraction(top, bottom);
    }
    /**
     * This calculates this - that.
     * @param that the BigFraction we are subtracting from this BigFraction
     * @return this - that
     */
    public BigFraction subtract(BigFraction that)
    {
        BigInteger top = num.multiply(that.denom).subtract(denom.multiply(that.num)); 
        BigInteger bottom = denom.multiply(that.denom);
        return new BigFraction(top, bottom);
    }
    /**
     * This calculates this*that.
     * @param that the BigFraction we are multiplying by this BigFraction
     * @return this*that
     */
    public BigFraction multiply(BigFraction that)
    {
        BigInteger top = num.multiply(that.num);
        BigInteger bottom = denom.multiply(that.denom);
        return new BigFraction(top, bottom);
    }
    /**
     * This calculates this/that.
     * @param that the BigFraction we are dividing into this BigFraction
     * @return this/that
     */
    public BigFraction divide(BigFraction that)
    {
        BigInteger top = num.multiply(that.denom);
        BigInteger bottom = denom.multiply(that.num);
        return new BigFraction(top, bottom);
    }
    /**
     * Test code lurks here.
     * @param args command-line arguments
     */
    public static void main(String[] args)
    {
        BigFraction bf = valueOf(3,4);
        System.out.println(bf);
        BigFraction gf = valueOf(-3, -4);
        System.out.println(gf);
        BigFraction hf = valueOf(-6, -8);
        System.out.println(hf);
        System.out.println(bf.equals(gf));
        BigFraction a = valueOf(1,2);
        BigFraction b = valueOf(1,3);
        System.out.println(a.add(b));
        BigFraction total = new BigFraction();
        for(int k = 1; k <= 1000; k++)
        {
            total = total.add(BigFraction.valueOf(1,k));
        }
        System.out.println(total);
    } 
    /**
     * This static factory method allows a BigFraction to be specified
     * with two <code>long</code>s.  
     * @param num the numerator we are using
     * @param denom the denominator we are using
     * @return The BigFraction num/denom.
     */
    public static BigFraction valueOf(long num, long denom)
    {
        return new BigFraction(BigInteger.valueOf(num), 
              BigInteger.valueOf(denom));
    }
}