Thursday, 22 December 2016

Chapter 13 Exercise 18, Introduction to Java Programming, Tenth Edition Y. Daniel LiangY.

13.18 (Use the Rational class)
Write a program that computes the following
summation series using the Rational class:

You will discover that the output is incorrect because of integer overflow (too large).
To fix this problem, see Programming Exercise 13.15.

import java.math.BigDecimal;
import java.math.RoundingMode;

public class BigRational extends Number implements Comparable<BigRational> {
    // Data fields for numerator and denominator
    private BigDecimal numerator = BigDecimal.ZERO;
    private BigDecimal denominator = BigDecimal.ONE;

    /** Construct a rational with default properties */
    public BigRational() {
        this(BigDecimal.ZERO, BigDecimal.ONE);
    }

    /** Construct a rational with specified numerator and denominator */
    public BigRational(BigDecimal numerator, BigDecimal denominator) {
        BigDecimal gcd = gcd(numerator, denominator);
        this.numerator = ((denominator.compareTo(BigDecimal.ZERO) > 0) ? BigDecimal.ONE : new BigDecimal(-1)).multiply(numerator).divide(gcd);
        this.denominator = denominator.abs().divide(gcd);
    }

    public BigRational(String decimal) {

        int index = (decimal.contains(".")) ? decimal.indexOf('.') : decimal.indexOf('/');
        BigDecimal d;
        BigDecimal n;
        // if string is in decimal form
        if (decimal.contains(".")) {
            int power = decimal.substring(index + 1, decimal.length()).length();
            d = new BigDecimal(Math.pow(10,power));
            n = new BigDecimal(new StringBuilder(decimal).deleteCharAt(index).toString());
        } else {
            // if string contains '/'
            n = new BigDecimal(decimal.substring(0, index));
            d = new BigDecimal(decimal.substring(index + 1, decimal.length()));
        }

        BigDecimal gcd = gcd(n, d);
        this.numerator = ((d.compareTo(BigDecimal.ZERO) > 0) ? BigDecimal.ONE : new BigDecimal(-1)).multiply(n).divide(gcd);
        this.denominator = d.abs().divide(gcd);

    }

    /** Find GCD of two numbers */
    private static BigDecimal gcd(BigDecimal n, BigDecimal d) {
        BigDecimal n1 = n.abs();
        BigDecimal n2 = d.abs();

        BigDecimal remainder = n1.remainder(n2);
        while (remainder.compareTo(BigDecimal.ZERO) > 0) {
            n1 = n2;
            n2 = remainder;
            remainder = n1.remainder(n2);
        }




        return n2;
    }

    /** Return numerator */
    public BigDecimal getNumerator() {
        return numerator;
    }

    /** Return denominator */
    public BigDecimal getDenominator() {
        return denominator;
    }

    /** Add a rational number to this rational */
    public BigRational add(BigRational secondBigRational) {
        BigDecimal n1 = numerator.multiply(secondBigRational.getDenominator());
        BigDecimal n2 = denominator.multiply(secondBigRational.getNumerator());
        BigDecimal n = n1.add(n2);

        BigDecimal d = denominator.multiply(secondBigRational.getDenominator());
        return new BigRational(n, d);
    }

    /** Subtract a rational number from this rational */
    public BigRational subtract(BigRational secondBigRational) {
        BigDecimal n1 = numerator.multiply(secondBigRational.getDenominator());
        BigDecimal n2 = denominator.multiply(secondBigRational.getNumerator());
        BigDecimal n = n1.subtract(n2);

        BigDecimal d = denominator.multiply(secondBigRational.getDenominator());
        return new BigRational(n, d);
    }

    /** Multiply a rational number to this rational */
    public BigRational multiply(BigRational secondBigRational) {
        BigDecimal n = numerator.multiply(secondBigRational.getNumerator());
        BigDecimal d = denominator.multiply(secondBigRational.getDenominator());
        return new BigRational(n, d);
    }

    /** Divide a rational number from this rational */
    public BigRational divide(BigRational secondBigRational) {
        BigDecimal n = numerator.multiply(secondBigRational.getDenominator());
        BigDecimal d = denominator.multiply(secondBigRational.numerator);
        return new BigRational(n, d);
    }

    @Override
    public String toString() {
        if (denominator.equals(BigDecimal.ONE))
            return numerator + "";
       else
            return numerator + "/" + denominator;
    }

    @Override // Override the equals method in the Object class
    public boolean equals(Object other) {
        if ((this.subtract((BigRational)(other))).getNumerator().equals(BigDecimal.ZERO))
            return true;
        else
            return false;
    }

    @Override // Implement the abstract intValue method in Number
    public int intValue() {
        return (int)doubleValue();
    }

    @Override // Implement the abstract floatValue method in Number
    public float floatValue() {
        return (float)doubleValue();
    }

    @Override // Implement the doubleValue method in Number
    public double doubleValue() {
        return numerator.divide(denominator).doubleValue();
    }

    public BigDecimal bigDecimalDouble() {
        return numerator.divide(denominator, 100, RoundingMode.HALF_DOWN);
    }

    @Override // Implement the abstract longValue method in Number
    public long longValue() {
        return (long)doubleValue();
    }

    @Override // Implement the compareTo method in Comparable
    public int compareTo(BigRational o) {
        if (this.subtract(o).getNumerator().compareTo(BigDecimal.ZERO) > 0)
            return 1;
        else if (this.subtract(o).getNumerator().compareTo(BigDecimal.ZERO) < 0)
            return -1;
        else
            return 0;
    }
}

public class Rational extends Number implements Comparable<Rational> {
    // Data fields for numerator and denominator
    private long[] r = new long[2];
    private static int NUMERATOR = 0;
    private static int DENOMINATOR = 1;

    /** Default constructor */
    public Rational() {
        this(0, 1);
    }

    /** Construct a rational with specified numerator and denominator */
    public Rational(long numerator, long denominator) {
        long gcd = gcd(numerator, denominator);
        r[NUMERATOR] = ((denominator > 0) ? 1 : -1) * numerator / gcd;
        r[DENOMINATOR] = Math.abs(denominator) / gcd;
    }

    /** Find GCD of two numbers */
    private long gcd(long n, long d) {
        long t1 = Math.abs(n);
        long t2 = Math.abs(d);
        long remainder = t1 % t2;

        while (remainder != 0) {
            t1 = t2;
            t2 = remainder;
            remainder = t1%t2;
        }

        return t2;
    }

    /** Return numerator */
    public long getNumerator() {
        return r[NUMERATOR];
    }

    /** Return denominator */
    public long getDenominator() {
        return r[DENOMINATOR];
    }

    /** Add a rational number to this rational */
    public Rational add(Rational secondRational) {
        long n = r[NUMERATOR] * secondRational.getDenominator() +
                r[DENOMINATOR] * secondRational.getNumerator();
        long d = r[DENOMINATOR] * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Subtract a rational number from this rational */
    public Rational subtract(Rational secondRational) {
        long n = r[NUMERATOR] * secondRational.getDenominator()
                - r[DENOMINATOR] * secondRational.getNumerator();
        long d = r[DENOMINATOR] * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Multiply a rational number to this rational */
    public Rational multiply(Rational secondRational) {
        long n = r[NUMERATOR] * secondRational.getNumerator();
        long d = r[DENOMINATOR] * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Divide a rational number from this rational */
    public Rational divide(Rational secondRational) {
        long n = r[NUMERATOR] * secondRational.getDenominator();
        long d = r[DENOMINATOR] * secondRational.r[NUMERATOR];
        return new Rational(n, d);
    }

    @Override
    public String toString() {
        if (r[DENOMINATOR] == 1)
            return r[NUMERATOR] + "";
        else
            return r[NUMERATOR] + "/" + r[DENOMINATOR];
    }

    /** Override the equals method in the Object class */
    public boolean equals(Object parm1) {
        return (this.subtract((Rational) (parm1))).getNumerator() == 0;
    }

    /** Override the hashCode method in the Object class */
    public int hashCode() {
        return new Double(this.doubleValue()).hashCode();
    }

    /** Override the abstract intValue method in java.lang.Number */
    public int intValue() {
        return (int)doubleValue();
    }

    /** Override the abstract floatValue method in java.lang.Number */
    public float floatValue() {
        return (float)doubleValue();
    }

    /** Override the doubleValue method in java.lang.Number */
    public double doubleValue() {
        return r[NUMERATOR] * 1.0 / r[DENOMINATOR];
    }

    /** Override the abstract longValue method in java.lang.Number */
    public long longValue() {
        return (long)doubleValue();
    }

    @Override
    public int compareTo(Rational o) {
        if ((this.subtract(o)).getNumerator() > 0)
            return 1;
        else if ((this.subtract(o)).getNumerator() < 0)
            return -1;
        else
            return 0;
    }
}

import java.math.BigDecimal;

public class Exercise_18 {


    public static void main(String[] args) {

        // using rational class
        Rational total = new Rational();
        for (int i = 1; i < 100; i++) {
            total = total.add(new Rational(i, i + 1));
            if (i < 10) {
                System.out.println("total = " + total);
            }

        }
        System.out.println(total + " = " + total.doubleValue());

        // using BigRational class
        BigRational r = new BigRational( BigDecimal.ZERO, new BigDecimal(1));

        for (int i = 1; i < 100; i++) {
            r = r.add(new BigRational(new BigDecimal(i), new BigDecimal(i + 1)));
            if (i < 10) {
                System.out.println("r = " + r);
            }

        }
        System.out.println("BigRational total = " + r);
        System.out.println("BigRational decimal form = " + r.bigDecimalDouble());
    }

}

No comments :

Post a Comment