Thursday 22 December 2016

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

13.16 (Create a rational-number calculator)
Write a program similar to Listing 7.9, Calculator.java. Instead of using integers,
use rationals, as shown in Figure 13.10a. You will need to use the split method in
the String class, introduced in Section 10.10.3, Replacing and Splitting Strings,
to retrieve the numerator string and denominator string, and convert strings into
integers using the Integer.parseInt method.

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;
    }
}
import java.util.ArrayList;
public class Exercise_16 {

    public static void main(String[] args) {

        String[] token = getTokens(args);

        if (token.length != 3 || !isValidOperator(token)) {
            System.out.println("Invalid arguments.");
            System.out.println("Usage: java Chapter_13.Exercise_16 1/2 * 8/17");
            System.exit(1);
        }

        BigRational operand1 = new BigRational(token[0]);
        BigRational operand2 = new BigRational(token[2]);

        BigRational answer = null;
        switch (args[1]) {
            case "+": answer = operand1.add(operand2); break;
            case "-": answer = operand1.subtract(operand2); break;
            case "*": answer = operand1.multiply(operand2); break;
            case "/": answer = operand1.divide(operand2); break;
        }

        System.out.println(operand1 + " " + args[1] + " " + operand2 + " = " + answer);
    }

    private static boolean isValidOperator(String[] token) {

        return  token[0].matches("[\\d]*[0-9]/[\\d]*[0-9]") &&
                token[1].matches("[\\-\\+\\*\\/]") &&
                token[2].matches("[\\d]*[0-9]/[\\d]*[0-9]");
    }

    private static String[] getTokens(String[] strings) {
        String merged = " ";
        for (String s : strings) {
            merged += " " + s;
        }

        String[] tokens = merged.split("[\\s ]");
        ArrayList<String> temp = new ArrayList<>();
        // remove blanks
        for (String s : tokens) {
            if (s.length() != 0) {
                temp.add(s);
            }
        }
        return temp.toArray(new String[temp.size()]);
    }

}

No comments :

Post a Comment