Java Training Course/JT07
Class Rational
We now leave the conventional programming style of C (and Pascal, BASIC, FORTRAN etc.), and we enter the field of real object-oriented programming. We rewrite the class Ratio from JT06, and we remove the static
qualifier from most methods. In the new class Rational
the first (implied) parameter is the current object this
in most cases. Instead of:
public static Ratio subtract(Ratio rat1, Ratio rat2) { return add(rat1, negate(rat2)); } // subtract(Ratio, Ratio)
we write:
public Rational subtract(Rational rat2) { return this.add(rat2.negate()); } // subtract(Rational)
Desired Methods
Besides the 4 basic arithmetic operations we want to implement some more useful methods. In this session, the following list should be expanded with proper documentation comments and method bodies:
public Rational abs() { ... } public Rational add(Rational rat2) { ... } public int compareTo(Rational rat2) { ... } public Rational divide(Rational rat2) { ... } public boolean equals(Rational rat2) { ... } public boolean isInteger() { return denominator == 1; } public int intValue() { return numerator / denominator; } public Rational max(Rational rat2) { return this.compareTo(rat2) > 0 ? this : rat2 } public Rational min(Rational rat2) { return this.compareTo(rat2) < 0 ? this : rat2 } public Rational multiply(Rational rat2) { ... } public Rational negate() { return new Rational(- numerator, denominator); } public Rational subtract(Rational rat2) { ... } public String toString() { ... }
Program Skeleton
/* Rational - Exact Fractions of Integers * @(#) $Id$ * 2017-09-23, Georg Fischer */ // package declaration goes here (later) import java.io.Serializable; // we have a 'toString' method import java.lang.Cloneable; // we have a 'clone' method import java.lang.Integer; // parseInt import java.lang.Math; // abs import java.lang.String; // substring, indexOf, valueOf import java.lang.System; // out.println() /** Class <em>Rational</em> represents an integer fraction * together with the arithmetic operations on such Rationals. * The denominator is always > 0. All arithmetic operations * return reduced fractions where GCD(numerator, denominator) = 1. * The methods have name, parameters and return values analogous to methods * of the Java object type BigInteger, see * https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html */ public class Rational implements Cloneable, Serializable { //---------------- // Internal Properties //---------------- /** value above the bar, before the slash */ private int numerator; /** value below the bar, after the slash */ private int denominator; //---------------- // Constructors //---------------- /** No-args constructor, creates 1/1 */ public Rational() { numerator = 1; denominator = 1; } // no-args constructor /** Constructor with numerator, creates a/1 * @param a numerator */ public Rational(int a) { numerator = a; denominator = 1; } // constructor(int) /** Constructor with numerator and denominator, creates a/b. * Also reduces and normalizes the fraction, that means: * <ul> * <li>divides the numerator and the denominator by * their greatest common divisor, if that is > 1,</li> * <li>makes the denominator always positive,</li> * <li>normalizes the denominator to 1 if the numerator is 0.</li> * </ul> * @param a numerator * @param b denominator */ public Rational(int a, int b) { numerator = a; denominator = b; int common = gcd(numerator, denominator); if (common > 1) { numerator /= common; denominator /= common; } if (numerator == 0) { denominator = 1; } else if (denominator < 0) { numerator = - numerator; denominator = - denominator; } } // constructor(int, int) /** Constructor from a String representation, creates a/b * @param str String of the form "a/b" */ public Rational(String str) { int slashPos = str.indexOf("/"); if (slashPos < 0) { str += "/1"; slashPos = str.length() - 2; } numerator = Integer.parseInt(str.substring(0, slashPos)); denominator = Integer.parseInt(str.substring(slashPos + 1)); Rational rat = new Rational(numerator, denominator); // this will reduce and normalize numerator = rat.getNum(); denominator = rat.getDen(); } // constructor(String) public Rational clone() { return new Rational(this.numerator, this.denominator); } // clone //---------------- // Internal getters for the properties of the class //---------------- /** Gets the numerator * @return the numerator of <em>this</em> Rational */ private int getNum() { return numerator; } // getNum() /** Gets the denominator * @return the denominator of <em>this</em> Rational */ private int getDen() { return denominator; } // getDen() //---------------- // Public methods //----------------
Code for desired methods goes here
//================ /** Test program, shows a series of fixed operations * @param args String array of commandline arguments */ public static void main(String[] args) { int iarg = 1; String str0 = "0/1"; Rational rat0 = new Rational(str0); while (iarg < args.length) { String str1 = args[iarg]; Rational rat1 = new Rational(str1); System.out.println( str0 + " + " + str1 + " = " + rat0.add (rat1).toString()); System.out.println( str0 + " - " + str1 + " = " + rat0.subtract (rat1).toString()); System.out.println( str0 + " * " + str1 + " = " + rat0.multiply (rat1).toString()); System.out.println( str0 + " / " + str1 + " = " + rat0.divide (rat1).toString()); System.out.println("max(" + str0 + ", " + str1 + ") = " + rat0.max (rat1).toString()); System.out.println("min(" + str0 + ", " + str1 + ") = " + rat0.min (rat1).toString()); System.out.println("isInteger(" + str0 + ") = " + rat0.isInteger() ); System.out.println("intValue (" + str0 + ") = " + rat0.intValue () ); System.out.println(); str0 = str1; rat0 = rat1; iarg ++; } // while iarg } // main } // Rational
< Previous: JT06 Preliminary Class Ratio
> Next: JT08 Discussion