Lecture 13 Example Rational numbers: a number is rational if it can be defined as the ratio between two integers Issues in object-oriented programming The class Rational completed Material from Holmes Chapter 7: sections 1 through to 4, except section 6 (nothing explicitly about this in Hubbard), the ratio of the length of a circle circumference to its diameter, is a classical example of non-rational number Note that is also equal to 1 3 A class for the rational numbers class Rational { Encapsulation [Rumbaugh] Encapsulation (or information hiding) consists of separating the external aspects of an object, which are accessible to other objects, from the internal implementation details of the object, which are hidden from other objects // attributes private int numerator; private int denominator; // constructors public Rational () { numerator = 0; denominator = 1; public Rational ( int num, int denom) { numerator = num; denominator = denom; // reduces the fraction to its simplest form 2 3-1
Methods Revisited The variables numerator denominator are private to a rational number object They can only be accessed through methods defined in the class To display a rational number one should add a method similar to the following to the class Rational: public void printfraction () { if (denominator == 1) Systemoutprintln(numerator); else Systemoutprintln(numerator + "/" + denominator); Remarks Initial definitions: Rational a = new Rational(1,2); Rational b = new Rational(3,4); Rational c; Information hiding: the user only types cadd(a,b) doesn t need to know that a rational is implemented as a pair Inside the method: The use of xnumerator it is fine inside the class Outside the class there should not be any reference to the class private attributes this identifies the object itself It may be needed when the method has to return an object of the same type 4 6 To add two rationals to produce another rational we follow the rule then simplify the result Object Properties Since objects are stored by reference equality assignment operations need to be hled with some care If a b are two objects in the same class a = b a == b only deal with the object pointers not with their values // Equality between the given rational another one public Rational add ( Rational x, Rational y) { numerator = xnumerator * ydenominator + ynumerator * xdenominator; denominator = xdenominator * ydenominator; <=== reference to the object itself! public boolean equals ( Rational x ) { return (( thisnumerator == xnumerator ) && ( thisdenominator == xdenominator)); Rational a, b = new Rational( 2, 3 ); a = b; 5 7
// Copying objects Rational a, b = new Rational( 2, 3 ); a = b; // This only sets the pointers! // Damaging side effect: // changes to b imply chnges to a! public Rational copy () { Rational x = new Rational ( thisnumerator, thisdenominator ); return x; a = bcopy(); Class analysis The external structure of the class Rational is described below class Rational { // attributes private int numerator; private int denominator; // constructors public Rational (); public Rational ( int num, int denum ); // methods public Rational add ( Rational x, Rational y ); public Rational subtract ( Rational x, Rational y ); public Rational multiply ( Rational x, Rational y ); public Rational divide ( Rational x, Rational y ); public void printfraction (); public boolean equals ( Rational x ); public Rational copy (); Rational numerator denominator add ( Rationalx, Rational y) subtract ( Rational x, Rational y) multiply ( Rational x, Rational y) divide ( Rational x, Rational y) printfraction () equals copy () 8 10 Case Study: Arithmetic of Rational Numbers Problem Devise a Java class for the rational numbers Define methods to perform the four arithmetic operations on two rational numbers Also, define methods to print a rational number, copy a rational number compare two numbers for equality Problem analysis The operations on rationals are defined as follows: Algorithm Design Most of the methods above have already been implemented We just need to add some pseudo-code for a gcd algorithm for makerational Rationals should be expressed in minimal form A rational is reduced in minimal form by finding gcd dividing but by this number We ll call makerational this function 9 11
Example Euclid GCD algorithm Let, This is probably the oldest algorithm ever http://wwwcut-the-knotcom/blue/euclidhtml It is described as the solution to Proposition VII2 in Euclid s Elements: http://aleph0clarkuedu/ djoyce/java/elements/tochtml Given two numbers not prime to one another, to find their greatest common measure 2322 = 654*3 + 360 gcd 654 = 360*1 + 294 gcd 360 = 294*1 + 66 gcd 294 = 66*4 + 30 gcd 66 = 30*2 + 6 gcd 30 = 6*5 gcd gcd gcd gcd gcd gcd Therefore, gcd 12 14 Problem Analysis The algorithm is based on the following two observations: 1 If then gcd This is indeed so because no number (, in particular) may have a divisor greater than the number itself (I am talking here of non-negative integers) 2 If, for integers, then gcd gcd Indeed, every common divisor of a b also divides r Thus gcd divides gcd is a common divisor of hence gcd gcd The reverse is also true because every divisor of also divides But, of course, gcd Therefore, Algorithm for the greatest common divisor 1 divideby find remainder 2 while remainder is not zero 3 assign to 4 assign remainder to 5 divideby find remainder 6 assign to gcd 13 15
Algorithm for minimising a rational number 1 calculate gcd for a given 2 divide by gcd 3 divide by gcd 4 if either is zero 5 assign to 6 else 7 calculate the gcd for absolute values of 8 if 9 divide by gcd 10 divide by gcd 11 else 12 divide by negative gcd 13 divide by negative gcd or private void makerational() { int gcd; int divisor = 0; gcd = greatestcommondivisor(numerator, denominator); numerator = numerator / gcd; denominator = denominator / gcd; if (numerator == 0 denominator == 0) denominator = Mathabs(denominator); else { divisor = greatestcommondivisor(mathabs(numerator), Mathabs(denominator)); if (denominator > 0) { numerator = numerator / divisor; denominator = denominator / divisor; else { numerator = numerator / (-divisor); denominator = denominator / (-divisor); 16 16-2 // chap_7\ex_1java // program to test the methods of the rational class import javaio*; class Rational { private int numerator; private int denominator; // private methods, not to be seen from the outside private int greatestcommondivisor(int n, int d) { int remainder = n % d; while (remainder!= 0) { n = d; d = remainder; remainder = n % d; return d; // constructors public Rational() { numerator = 0; denominator = 1; public Rational(int num, int denom) { numerator = num; denominator = denom; // methods public Rational add(rational x, Rational y)d { numerator = xnumerator * ydenominator + ynumerator * xdenominator; denominator = xdenominator * ydenominator; 16-1 16-3
public Rational subtract(rational x, Rational y) { numerator = xnumerator * ydenominator - ynumerator * xdenominator; denominator = xdenominator * ydenominator; public Rational multiply(rational x, Rational y) { numerator = xnumerator * ynumerator; denominator = xdenominator * ydenominator; public Rational divide(rational x, Rational y) { numerator = xnumerator * ydenominator; denominator = xdenominator * ynumerator; class Ex_1 { public static void main(string[] args) throws IOException { Rational a = new Rational(-8,3); Rational b = new Rational(9,4); Rational c = new Rational(); Rational d; Systemoutprint("a="); aprintfraction(); Systemoutprint("b="); bprintfraction(); Systemoutprint("a+b="); cadd(a,b)printfraction(); Systemoutprint("a-b="); csubtract(a,b)printfraction(); Systemoutprint("a*b="); cmultiply(a,b)printfraction(); Systemoutprint("a/b="); cdivide(a,b)printfraction(); d=acopy(); Systemoutprint("d="); dprintfraction(); if (dequals(a)) Systemoutprintln("Both d a are equal"); 16-4 16-6 public void printfraction() { if (denominator == 1) Systemoutprintln(numerator); else Systemoutprintln(numerator + "/" + denominator); public boolean equals(rational x) { return ((thisnumerator == xnumerator) && (thisdenominator == xdenominator)); public Rational copy() { Rational temporary = new Rational(thisnumerator, thisdenominator); return temporary; Exercises 1 Draw a class diagram for the code in the example above 2 Extend the class Rational by implementing a between two rational numbers relation 3 To improve the accuracy of the numerical calculation involved replace int with long This should be transparent to the user 4 Repeat similar construction for complex numbers This is exercise 36 on page 276 16-5 17