Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

CSC-1106 Homework 09 (Class and static methods) Due: Tuesday, November 22, 2016

ID: 3778809 • Letter: C

Question

CSC-1106 Homework 09 (Class and static methods) Due: Tuesday, November 22, 2016 rite a class encapsulating the concept of a rational number, a rational number has the following attributes: an integer representing the numerator of the rational number, and another integer representing the denominator of the rational number. The ratio should always be stored in its simplest form. For example, the rational number 40/12 should be stored as 103. The class has the following constructors and methods: A default constructor to set the Rational number to 0/1 A constructor that has parameters for the numerator and denominator, and converts the resulting ratio to simplified form simplify 0-a private method to convert the Rational number to simplified form getGCD (x,y)-a private static method to return the largest common factor of the two positive integers x and y (their greatest common divisor). For example, the greatest common divisor of 40 and 12 is 4. value 0-returns the Rational number as a double value tostring o-returns the Rational number as a string in the form a/b multiply (Rational -a public method to return the Rational number after multiplied by Rational number r add (Rational r)-a public method to return the Rational number after addition with Rational number r floor (Rational r) -a public method to return the integer of the floor of the Rational number. max (Rational x, Rational )-a public static method to return the larger Rational number among x and y.

Explanation / Answer

Rational.java

public class RationalNo {

    public static final RationalNo ZERO = new RationalNo(0, 1);

    public static final RationalNo RationalNo(1, 1);

    public static final RationalNo HALF = new RationalNo(1, 2);

    private static final double LWST_PREC = 1E-3;

    private static final double HIST_PREC = 1E-16;

    private static double precision = 1E-10;

    private final long num;

    private final long den;

    private final double result;

    public RationalNo(long numtr, long denmtr) {

        if (denmtr == 0) {

            den = 0;

            if (numtr > 0) {

                num = 1;

                result = Double.POSITIVE_INFINITY;

            } else if (numtr < 0) {

                num = -1;

                result = Double.NEGATIVE_INFINITY;

            } else {

                num = 0;

                result = Double.NaN;

            }

            return;

        }

        if (denmtr < 0) {

            numtr = 0L - numtr;

            denmtr = 0L - denmtr;

        }

        num = numtr;

        den = denmtr;

        result = (double) numtr / denmtr;

    }

    public RationalNo(double decimal) {

        if (decimal == Double.NaN) {

            num = 0;

            den = 0;

            result = Double.NaN;

            return;

        }

        if (decimal == Double.POSITIVE_INFINITY) {

            num = 1;

            den = 0;

            result = Double.POSITIVE_INFINITY;

            return;

        }

        if (decimal == Double.NEGATIVE_INFINITY) {

            num = -1;

            den = 0;

            result = Double.NEGATIVE_INFINITY;

            return;

        }

        long nu, de;

        long whole = 0;

        boolean negative = decimal < 0;

        decimal = Math.abs(decimal);

        boolean hasWhole = decimal >= 1;

        if (hasWhole) {

            whole = (long) decimal;

            decimal -= whole;

        }

        if (decimal == 0) {

            num = negative ? 0L - whole : whole;

            den = 1;

            result = negative ? 0D - whole : whole;

            return;

        }

        long n1 = 0, d1 = 1;

        long n2 = 1, d2 = 1;

        double epsilon;

        while (true) {

            long n = n1 + n2, d = d1 + d2;

          double result = (double) n / d;

            epsilon = Math.abs(result - decimal);

            if (epsilon <= precision) {

                nu = n;

                de = d;

                break;

            } else if (result < decimal) {

                n1 = n;

                d1 = d;

            } else {

                n2 = n;

                d2 = d;

            }

        }

        if (hasWhole) {

            nu += de * whole;

        }

        num = negative ? 0L - nu : nu;

        den = de;

        result = (double) num / den;

    }

    public static double getPrecision() {

        return precision;

    }

    public static void setPrecision(double precision) {

        if (precision < 0) {

            precision = 0D - precision;

        }

        if (precision < HIST_PREC) {

            precision = HIST_PREC;

        } else if (precision > LWST_PREC) {

            precision = LWST_PREC;

        }

        RationalNo.precision = precision;

    }

    private static long gcf(long a, long b) {

        if (a == 0 || b == 0) {

            return 0;

        }

        if (a < 0) {

            a = 0L - a;

        }

        if (b < 0) {

            b = 0L - b;

        }

        if (a < b) {

            long t = a;

            a = b;

            b = t;

        }

        long r;

        do {

            r = a % b;

            a = b;

            b = r;

        } while (r > 0);

        return a;

    }

    public static void main(String[] args) {

        RationalNo PI = new RationalNo(Math.PI);

        System.out.println("Pi = " + PI);

    }

    public RationalNo reduce() {

        long gcf = gcf(num, den);

        if (gcf == 0) {

            return this;

        } else {

            long n = num / gcf;

            long d = den / gcf;

            return new RationalNo(n, d);

        }

    }

    public RationalNo add(RationalNo rational) {

        if (this.result == Double.NaN) {

            return this;

        } else if (rational.result == Double.NaN) {

            return rational;

        }

        RationalNo o = reduce();

        long n1 = o.num, d1 = o.den;

        o = rational.reduce();

        long n2 = o.num, d2 = o.den;

        return new RationalNo(n1 * d2 + n2 * d1, d1 * d2).reduce();

    }

    public RationalNo subtract(RationalNo rational) {

        return add(new RationalNo(0L - rational.num, rational.den));

    }

    public RationalNo multiply(RationalNo rational) {

        return new RationalNo(

                this.num * rational.num,

                this.den * rational.den)

                .reduce();

    }

    public RationalNo divide(RationalNo rational) {

        return multiply(rational.reciprocate());

    }

    public RationalNo reciprocate() {

        return new RationalNo(den, num);

    }

    public double toDouble() {

        return result;

    }

    @Override

    public String toString() {

        return Long.toString(num).concat("/").concat(Long.toString(den));

    }

    @Override

    public boolean equals(Object another) {

        if (another instanceof RationalNo) {

            RationalNo oldF = reduce();

            RationalNo newF = ((RationalNo) another).reduce();

            return (oldF.num == newF.num)

                    && (oldF.den == newF.den);

        }

        return false;

    }

    public RationalNo pow(int p) {

        RationalNo result = ONE;

        RationalNo n = new RationalNo(num, den);

        boolean neg = p < 0;

        if (neg) {

            p = 0 - p;

        }

        while (p > 0) {

            if ((p & 1) == 1) {

                result = result.multiply(n);

                p--;

            }

            n = n.multiply(n);

            p >>>= 1;

        }

        return neg ? result.reciprocate() : result;

    }

    public RationalNo pow(RationalNo p) {

        return new RationalNo(Math.pow(this.result, p.result));

    }

}

TestCase:

import junit.framework.TestCase;

public class TestRational extends TestCase {

    public void addTest() {

        RationalNo r1, r2;

        r1 = new RationalNo(10, 20);

        r2 = new RationalNo(20, 30);

        assertEquals(new RationalNo(7, 6), r1.add(r2));

    }

    public void subtractTest() {

        RationalNo r1, r2;

        r1 = new RationalNo(20, 30);

        r2 = new RationalNo(10, 20);

        assertEquals(new RationalNo(1, 6), r1.subtract(r2));

    }

    public void multiplyTest() {

        RationalNo r1, r2;

        r1 = new RationalNo(0.5);

        r2 = new RationalNo(2);

        assertEquals(RationalNo.ONE, r1.multiply(r2));

    }

    public void divideTest() {

        RationalNo r1, r2;

        r1 = new RationalNo(0.5);

        r2 = new RationalNo(0.0625);

        assertEquals(new RationalNo(8), r1.divide(r2));

    }

    public void powTest() {

        assertEquals(RationalNo.ONE, new RationalNo(2).pow(RationalNo.ZERO));

        assertEquals(new RationalNo(1, 64), new RationalNo(1, 4).pow(3));

    }

}