Manual - Marquette University



PURPOSE

THE FRACTION CLASS IS ANOTHER EXAMPLE OF A UTILITY CLASS THAT ALLOWS YOU TO WRITE METHODS THAT ARE MORE COMPLEX. YOU WILL WRITE METHODS THAT

▪ are passed objects

▪ create and return new objects.

▪ use if – else

▪ provide a private service and are not available for public use

To prepare

▪ READ WU: CHAPTER 4

▪ Read through this laboratory session

To Complete

▪ THIS IS AN INDIVIDUAL LAB. YOU MAY ASK THE LAB TUTOR FOR HELP AND YOU MAY CONSULT WITH YOUR NEIGHBOR IF YOU ARE HAVING DIFFICULTIES.

▪ Complete Post Lab Exercises #1 ________ and #2 _______

▪ Your grade for the lab will be determined by handing in a hardcopy of your final Fraction.java and the result of one run of the program.

7.1 Writing a Fraction Class

JAVA PROVIDES THE PRIMITIVE TYPES DOUBLE AND FLOAT TO STORE FRACTIONAL VALUES THAT, WHEN PRINTED, ARE IN DECIMAL FORM. SOME ELEMENTARY SCHOOL CALCULATORS WORK WITH FRACTIONS IN THE FORM [pic]. LET'S DESIGN A CLASS CALLED FRACTION THAT STORES THE NUMERATOR AND DENOMINATOR OF A FRACTION, WHICH WILL BE THE INSTANCE VARIABLES OF A FRACTION OBJECT. THE METHODS SHOULD INCLUDE

o constructors to create Fraction objects

o methods that allow two Fractions objects to be added, subtracted, multiplied and divided

o methods to allow display of the Fraction in the form numerator/denominator

o a method that finds the decimal equivalent of the Fraction

o methods to compare two Fraction objects for equality, is less than and is greater than.

Step 1: We start with one constructor, Fraction(int num, int den), and a toString method. This is enough to allow a client to create and print a Fraction object. We will design the client as a developer might by including a main method in the Fraction class for testing purposes. Once the Fraction class is developed, rather than omitting the main method, it can be commented out, thus allowing further testing if changes are made to the class.

Begin the class definition by entering the following in the file Fraction.java.

class Fraction

{

//instance variables

private int numerator, denominator;

//constructors

public Fraction(int num, int den)

{

numerator = num;

denominator = den;

}

public String toString()

{

return numerator + "/" + denominator;

}

//The Fraction class is meant to be a utility class, used by a client

//class. The main method is present for testing purposes by the author

//of the class. It should be commented out after the class is made

//available.

public static void main(String[] args)

{

Fraction f1 = new Fraction(3,4);

System.out.println(f1);

}

}

Compile and run the program. Record the results.

_____________________________________________________________________________________________

Draw a state of memory diagram for the main method. When drawing the Fraction object be sure to include the values stored in the object's instance variables.

Passing and Returning Objects

To add two Fraction objects and find the sum, an instance method called plus is needed. The method is invoked on a Fraction, the first addend. The second addend must be passed to the method. The sum of the addends, a Fraction is returned. The header of the method is

public Fraction plus(Fraction other)

the sum the second fraction

Before we write the method, let's write some statements that correctly call the plus method.

Step 2: Add, to the main method, this code that finds and prints the sum of 3/4 and 1/6.

Fraction f2, sum;

f2= new Fraction(1,6);

sum = f1.plus(f2);

System.out.println(f1 + " + " + f2 + " = " + sum);

There are now three Fraction objects. Add these changes to the state of memory diagram above. Fill in the values stored in each object's instance variables.

Step 3: Recall that to add two fractions a common denominator is needed. While it is not necessarily the least common denominator, the product of the two denominators is a common denominator.

or using f1 and f2

Look carefully at this state of memory diagram of the main method that illustrates the method plus as it is invoked on the Fraction f1.

Fraction sum = f1.plus(f2);

The method plus has a parameter other of type Fraction that has been passed f2. Therefore, other stores a copy of the reference f2. That is, when an object is passed to a method, a reference is passed, i.e. objects are passed by reference.

The "cleanest" code that implements what is shown above is

public Fraction plus(Fraction other)

{

int den = denominator * other.denominator;

int num = numerator * other.denominator + denominator * other.numerator;

return new Fraction(num, den);

}

The line

int den = denominator * other.denominator;

calculates the common denominator. den is a local variable that exists only during the execution of the method. denominator is the instance variable belonging to this object, the object on which the method is invoked. Therefore, another way to refer to denominator is this.denominator. The above statement can be replaced with

int den = this.denominator * other.denominator;

which is often preferred by students. The choice is yours.

Similarly, the second statement could be modified using the reference to the current object, this. Notice, that even though other's instance variables are private, the plus method has direct access to them (other.numerator and other.denominator) because plus is a method defined in the Fraction class.

Also, the statement

return new Fraction(num, den);

could be replaced with the two statements

Fraction answer = new Fraction(num, den);

return answer;

Again, the choice is yours.

Step 3: Add the plus method to the Fraction class. Compile the code and run the program. Record what is printed.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

7.2 Using the selection statements if and If – else

A SELECTION STATEMENT ALLOWS A CHOICE TO BE MADE AS TO WHICH STATEMENTS WILL BE EXECUTED BASED ON SOME CONDITION. A SELECTION STATEMENT CAN BE USED TO IMPROVE THE CONSTRUCTOR OF THE FRACTION CLASS,

public Fraction(int num, int den)

{

numerator = num;

denominator = den;

}

which currently allows fractions with a negative integer in the denominator, such as -3/-2 and 4/-3, to be created. Converting these two fractions to 3/2 and -4/3 would be preferable. This change can be made by multiplying both num and den by -1 if den is a negative number. That is,

if(den < 0)

{

num = num * -1;

den = den * -1;

}

The braces are needed to create a block of statements that are executed in the event that the denominator is less than ( < ) zero.

Another condition that should be checked is the possibility that the client could pass zero to den. Since a Fraction with a denominator of zero is illegal we have two choices:

1. Change the denominator to another value, such as 1.

2. Refuse to create a new Fraction by instead throwing an illegal argument exception.

The second choice is probably preferable, but that is a topic that we are not ready to discuss. Therefore, we will implement the first choice.

Step 4: Add a class constant to the Fraction class

public static final int DEFAULT_DENOMINATOR = 1;

and then modifiy the constructor to

public Fraction(int num, int den)

{

if(den < 0)

{

num *= -1;

den *= -1;

}

if(den == 0)

{

den = DEFAULT_DENOMINATOR;

}

numerator = num;

denominator = den;

}

A flow chart for this code is

Now, add statements to the main method that create and print the fractions -3/-2, 4/-3 and 5/0. Compile the code and run the application. Record what is printed.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

Step 5: Notice that if den is less than zero, it is not necessary and, therefore, it is inefficient to test if den is equal to zero. Instead of using two if structures, an if – else structure should be used.

if(den < 0)

{

num *= -1;

den *= -1;

}

else if(den == 0)

{

den = DEFAULT_DENOMINATOR;

}

What does this do to the flow chart on the previous page?

A flow chart for this code is

Make this change to the constructor. Compile and run the program.

Step 6: An if – else structure is also needed in an equals method for the Fraction class. Two fractions are equal if the results of cross multiplying are equal. That is [pic]. One version of equals is

public boolean equals(Fraction other)

{

if(numerator * other.denominator == other.numerator * denominator)

return true;

else

return false;

}

Draw a flow chart diagram of the equals method.

Add the equals method to the Fraction class and uncomment this code, that tests equals, in the main method.

System.out.print(sum + " and " + f1 + " are ");

if(sum.equals(f1))

System.out.println("equal");

else

System.out.println("not equal");

System.out.print(sum + " and 11/12 are " );

if(sum.equals(new Fraction(11,12)))

System.out.println("equal");

else

System.out.println("not equal");

Compile the code and run the application. Record the results.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

7.3 Another use for the reserved word this

IN MOST CASES, THERE IS MORE THAN ONE CONSTRUCTOR FOR AN OBJECT. GENERALLY, THE CONSTRUCTOR THAT INITIALIZES THE MOST DATA MEMBERS DOES ALL OF THE WORK AND THE OTHER CONSTRUCTORS CALL THIS CONSTRUCTOR. CONSIDER A SECOND CONSTRUCTOR THAT IS PASSED ONLY THE NUMERATOR AND CONSTRUCTS A FRACTION THAT IS A WHOLE NUMBER.

public Fraction(int num)

{

this(num, DEFAULT_DENOMINATOR);

}

The single statement calls another constructor for this object that has two formal parameters of type int, passing num and 1 as the numerator and denominator.

Step 7: Add the new constructor to the Fraction class and statements that call the constructor and print the new Fraction. Compile and run the program. Record the new statements that you added and the printed result.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

Step 8: Introduce a second class constant to store the default numerator of zero. Following the previous example, write a third constructor that has no parameters and initializes the numerator and denominator to their default values. Compile and run the program. Record the new statements that you added and the printed result.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

7.4 Reducing a Fraction

TO REDUCE A FRACTION, THE NUMERATOR AND DENOMINATOR ARE EACH DIVIDED BY THEIR GREATEST COMMON DIVISOR, WHICH AT LEAST IS ONE. A METHOD TO FIND THE GREATEST COMMON DIVISOR OF TWO INTEGER VALUES USES A LOOP. IN CLASS AND IN PREVIOUS LABS, YOU HAVE BEEN INTRODUCED TO THE WHILE LOOP. UNDERSTANDING THE MATHEMATICAL ALGORITHM THAT THIS METHOD USES IN NOT NEEDED. HOWEVER, YOU SHOULD BE ABLE TO FOLLOW THE CODE. A FLOWCHART IS SHOWN TO HELP YOU FOLLOW THE CODE.

|int gcd(int a, int b) | |

|{ | |

|a = Math.abs(a); | |

|b = Math.abs(b); | |

| | |

|while (b != 0) | |

|{ | |

|int r = a % b; | |

|a = b; | |

|b = r; | |

|} | |

| | |

|return a; | |

|} | |

| | |

| | |

The first two lines assign the absolute values of the a and b to a and b using the Math class method

public int abs(int n)

Next, the condition for the loop, b != 0 (b is not equal to zero) is evaluated to true or false. If true, the three statements in the body of the loop are executed. Notice, that the local variable r is declared inside the block of statements that is the body of the loop and, therefore, is known only inside the body of the loop. Also, notice that the value of b is changed inside the body of the loop and, therefore, the next time the loop condition is evaluated b has stores a new value.

Using a is 24 and b is -45, follow the code, recording the state of memory for the method in a chart

| |r |a |b |b != 0 |

|a and b have been passed 24 and -45 | |24 |-45 | |

|After finding |a| and |b| and evaluating the condition | |24 |45 |true |

|After the body of the loop is executed the first time |24 |45 |24 |true |

| " the second time |21 |24 |21 |true |

| " the third time |3 |21 |3 |true |

| " the fourth time |0 |3 |0 |false |

Since b != 0 is false, the loop ends and control goes to the statement following the body of the loop. So, the value stored in a, the least common denominator of 24 and -45, is returned.

Since the client is not expected to call this method, the method should be modified by private to restrict its use to inside the Fraction class only. Add the method to the Fraction class.

private int gcd(int a, int b)

{

a = Math.abs(a);

b = Math.abs(b);

while (b != 0)

{

int r = a % b;

a = b;

b = r;

}

return a;

}

Step 9: Follow the code of the gcd method by making a list of the variables and the values they store if the values passed are gcd(22, 24)

To actually reduce a Fraction, we need a method that reduces the current Fraction by dividing the numerator and denominator of this Fraction by the value returned by the gcd method. This method could be public if the client is expected to reduce a Fraction. Or, the method could be private if every Fraction is reduced when it is created. The second approach is the one we will take. Therefore, the method is modified by private and is called from the constructor. Add this method to the Fraction class.

private void reduce()

{

int greatestCommonDivisor = gcd(numerator, denominator);

numerator = numerator / greatestCommonDivisor;

denominator /= greatestCommonDivisor;

}

To call the reduce method from the constructor, add the statement

reduce();

as the last statement in the constructor Fraction(int, int).

Compile the code and run the application. Record any changes that you notice in the output of the program.

_____________________________________________________________________________________________

_____________________________________________________________________________________________

_____________________________________________________________________________________________

7.5 Post-laboratory Exercises

1. MODIFY THE FRACTION CLASS BY MODIFYING OR ADDING SOME OR ALL OF THE FOLLOWING METHODS. FOR EACH METHOD ADD CODE TO THE MAIN METHOD THAT TESTS IT.

A. public Fraction minus(Fraction other) returns the difference of this object and other.

Add code to main to find and print the difference of f1 and f2 and of 0 and f1.

B. public Fraction times(Fraction other) returns the product of this object and other.

Add code to main to find and print the product of f1 and f2 , of 0 and f1, and 5 and -2/3.

C. public Fraction dividedBy(Fraction other) returns the quotient of this object and other. If other equals zero, the null reference should be returned.

Add code to main to find and print the quotient of f1 and f2, of f1 and 0, and f1 and 5.

D. public double toDecimal() returns the decimal equivalent of this object expressed as a double.

Add code to main to print the decimal equivalent of f1, -3/7 and 0.

E. public Fraction reciprocal() returns the reciprocal of this object unless this object equals zero, in which case the null reference is returned.

Add code to main to find and print the reciprocals of f1, f2 and 0.

F. public boolean isLessThan(Fraction other) returns true if this object is less than other.

Add code to main to print if f1 is less than f2, if f2 is less than f1, and if f1 is less than f1.

G. public boolean isGreaterThan(Fraction other) returns true if this object is less than other.

Add code to main to determine if f1 is greater than f2, if 0 is greater than f1, and if f1 is greater than -5.

H. Modify public String toString() so that whole number fractions are expressed without the denominator of one. i.e. 5/1 should be expressed as 5 instead of 5/1. Add testing.

I. public String toMixedString() that returns a String representation of this object as a mixed number if the numerator is larger than the denominator. Otherwise, the toString() representation is returned. Add testing.

2. Add code to the main testing method in the Fraction class to calculate and print each of the following.

Each calculation should be a single statement.

A. [pic] B. [pic] C. [pic]

3. Write a class Point that represents the coordinates of a point (x,y) in a two-dimensional coordinate system. The class should also contain a main method to test each method as it is written.

Data Members: Two private variables of type double representing the x and y coordinates.

Constructors:

public Point(double x, double y) initializes the two coordinates

public Point() initializes the two coordinates to 0

Public Methods:

A. public String toString() returns a String representation "(x, y)"

B. Accessor and mutator methods for both instance variables.

C. public double distanceBetween(Point p) returns the distance between this Point and Point p

D. public double distanceToOrigin() returns the distance between this Point and (0,0)

E. public Point midpoint(Point p) returns the midpoint between this Point and Point p

F. public void translate(double changeInX, double changeInY) changes the x coordinate of this

Point by changeInX and changes the y coordinate by changeInY

G. public boolean equals(Point p) returns true if this Point and p represent the same coordinates

and false otherwise.

H. public double slope(Point p) returns the slope of the line between this Point and p. If two points

have the same x value, the line is vertical and its slope is undefined. In this case you should

return the static constant NaN defined in class Double. NaN stands for Not – a – Number and is

a double value.

I. public String lineEquation(Point p) returns the equation of the line between this Point and p.

Again, a vertical line is a special case.

Suppose you have two points P (x1, y1) and Q (x2, y2)

• Then the distance between P and Q is [pic]

• The midpoint between P and Q is [pic]

• The slope of the line between P and Q is [pic]

• The equation of the line between P and Q is [pic] where [pic] is the slope of the line and [pic] . The equation of a vertical line is [pic].

-----------------------

true

return a;

int r = a % b;

a = b;

b = r;

b != 0

a = Math.abs(a);

b = Math.abs(b);

false

true

numerator = num;

denominator = den;

den = 1

den == 0

false

true

num *= -1

den *= -1

den < 0

false

true

numerator = num;

denominator = den;

den = 1

den == 0

false

true

num *= -1

den *= -1

den < 0

Note: These braces are optional since the body of the if contains only a single statement.

return

24

22

Fraction

numerator

denominator

22

24

other

num

den

method plus

4

3

Fraction

numerator

denominator

6

1

Fraction

numerator

denominator

f2 f1 sum

[pic]

[pic]

L A B

7

false

Object Oriented Programming in Java

Another Utility Class

Using if-else

................
................

In order to avoid copyright disputes, this page is only a partial summary.

Google Online Preview   Download