UNB/ CS/ David Bremner/ teaching/ java/ BigRational.java
import java.math.BigInteger;
import java.math.BigDecimal;

class BigRational extends Number{
    
    private BigInteger numer,denom;

    public static final int APPROX_DIGITS=32;

    public BigRational(BigInteger theNumer,BigInteger theDenom){
        numer=theNumer;
        denom=theDenom;
        normalize();
    }


    private void normalize(){
        BigInteger oldNumer=numer;
        
        numer=numer.divide(oldNumer.gcd(denom));
        denom=denom.divide(oldNumer.gcd(denom));

        if (denom.signum()==-1){
            numer=numer.negate();
            denom=denom.negate();
        }
    }

    public BigRational(long numerInt,long denomInt){
        this(BigInteger.valueOf(numerInt),BigInteger.valueOf(denomInt));
    }
    public BigRational(String numerString){
        this(numerString,"1");
    }

    public BigRational(String theNumer,String theDenom){
        this(new BigInteger(theNumer),
                    new BigInteger(theDenom));
    }

    public BigDecimal toBigDecimal(){
        BigDecimal decNum=new BigDecimal(numer).setScale(APPROX_DIGITS);
        BigDecimal decDen=new BigDecimal(denom);
        
        return (decNum.divide(decDen,BigDecimal.ROUND_HALF_UP));
    }

    public String toString(){
        if (denom.equals(BigInteger.ONE)){
            return numer.toString();
        } else {
            return numer.toString() + ":" + denom.toString();
        }
    }

        
    public BigInteger integerPart(){
        return numer.divide(denom);
    }

    
    public byte byteValue() {
        return integerPart().byteValue();
    }

    public double doubleValue(){
        return toBigDecimal().doubleValue();
    }

    public float floatValue(){
        return (float)doubleValue();
    }
    
    public int intValue(){
        return integerPart().intValue();
    }
    
    public long longValue() {
        return integerPart().longValue();
    }

    public BigRational add(BigRational by){

        BigInteger newDenom=this.denom.multiply(by.denom);
        BigInteger newNumer=this.numer.multiply(by.denom);
        
        newNumer=newNumer.add(by.numer.multiply(this.denom));
        
        return new BigRational(newNumer,newDenom);
    }

                               
    public BigRational multiply(BigRational by){
        return new BigRational(this.numer.multiply(by.numer),
                               this.denom.multiply(by.denom));
    }

    public BigRational negate(){
        BigRational retVal=new BigRational(numer,denom);
        
        retVal.numer=retVal.numer.negate();
        
        return retVal;
    }

    public BigRational reciprocal(){
        return new BigRational(denom,numer);
    }

    public BigRational subtract(BigRational other){
        return this.add(other.negate());
    }

    public BigRational divide(BigRational other){
        return this.multiply(other.reciprocal());
    }
    public static void main(String[] args){
        
        BigRational r=new BigRational("-22","-4");
        
        System.out.println(r);
        System.out.println(r.multiply(r).subtract(r).divide(r).negate());

        BigRational p=new BigRational("10001");
        System.out.println(p);
        
        BigRational q=new BigRational("99999999");
        System.out.println(q);
        
        System.out.println(p.divide(q).multiply(q));
        

        
    }   
}