Block B

To reduce a frction, we divide the numerator and denominator by their greatest commond divisor. Let's do this in Python


from math import gcd
class BigFraction:
    def __init__(self, num = 0, denom = 1):
        d = gcd(num, denom)
        self.num = num//d
        self.denom = denom//d
    def __str__(self):
        return f"{self.num}/{self.denom}"
def main():
    a = BigFraction(3,5)
    b = BigFraction(10) 
    c = BigFraction()
    print(f"a = {a}, b = {b}, c = {c}")
    d = BigFraction(3,6)
    print(f"d = {d}")
main()

Now all of our BigFractions are born fully reduced.


from math import gcd
class BigFraction:
    def __init__(self, num = 0, denom = 1):
        d = gcd(num, denom)
        self.num = num//d
        self.denom = denom//d
    def __str__(self):
        return f"{self.num}/{self.denom}"
    def __add__(self, other):
        top = self.num*other.denom + self.denom*other.num
        bottom = self.denom*other.denom
        return BigFraction(top, bottom)
    def __sub__(self, other):
        top = self.num*other.denom - self.denom*other.num
        bottom = self.denom*other.denom
        return BigFraction(top, bottom)
def main():
    a = BigFraction(3,5)
    b = BigFraction(10) 
    c = BigFraction()
    print(f"a = {a}, b = {b}, c = {c}")
    d = BigFraction(3,6)
    print(f"d = {d}")
    e = BigFraction(3,-6)
    print(f"e = {e}")
main()

Note how e prints out as 1/-2. This is aesthetically unpleasing. So what we do is to kick the negative upstairs with a little conditional logic.


from math import gcd
class BigFraction:
    def __init__(self, num = 0, denom = 1):
        d = gcd(num, denom)
        if denom < 0:
            num = -num
            denom = -denom  ##kick any negative upstairs
        self.num = num//d
        self.denom = denom//d
    def __str__(self):
        return f"{self.num}/{self.denom}"
def main():
    a = BigFraction(3,5)
    b = BigFraction(10) 
    c = BigFraction()
    print(f"a = {a}, b = {b}, c = {c}")
    d = BigFraction(3,6)
    print(f"d = {d}")
    e = BigFraction(3,-6)
    print(f"e = {e}")
main()

Our BigFraction objecs are born fully reduced, and any negative is in the numerator. This will ease our path down the road a great deal.

Now let's pay attention to the Java side.


import java.math.BigInteger;
public class BigFraction
{
    private final BigInteger num;
    private final BigInteger denom;
    public BigFraction(BigInteger num, BigInteger denom)
    {
        BigInteger d = num.gcd(denom);
        num = num.divide(d);
        denom = denom.divide(d);
        this.denom = denom;
        this.num = num;
    }
    public BigFraction(BigInteger num)
    {
        this(num, BigInteger.ONE);
    }
    public BigFraction()
    {
        this(BigInteger.ZERO, BigInteger.ONE);
    }
    public String toString()
    {
        return String.format("%s/%s", num, denom);
    }
    public static void main(String[] args)
    {
        BigFraction a = new BigFraction(BigInteger.valueOf(3),
             BigInteger.valueOf(5));
        BigFraction b = new BigFraction(BigInteger.valueOf(10), 
        BigInteger.ONE);
        BigFraction c = new BigFraction();
        System.out.printf("a = %s, b = %s, c = %s\n", a, b, c);
        BigFraction d = new BigFraction(
            BigInteger.valueOf(7776), BigInteger.valueOf(-243));
        System.out.println(d);
    }
}

Now we get the negative upstairs. Note the


       a      c        ad  +  bc
      --- +  ---  =   -----------
       b      d           bd

      num        that.num            num*that.denom  +  denom*that.num
      ---     +  -----------   =     ---------------------------------
     denom       that.denom                denom* that.denom

     top = num.multiply(that.denom).add(denom.multiply(that.num))

     bottom = denom.multiply(that.denom);