Question
Java* Part II: Class Fractions (40 point) ------------------------------- This part has 4 sub-parts (A, B, C and D). Create a project in Eclipse and call
Java*
Part II: Class Fractions (40 point)
------------------------------- This part has 4 sub-parts (A, B, C and D). Create a project in Eclipse and call it Fractions. Add the class Fractions.java to this project. Look at the main method in the Fraction class, which declares and constructs four Fraction objects. Four different constructors are used, each with different parameters.
Fraction f0 = new Fraction(); Fraction f1 = new Fraction(3); Fraction f2 = new Fraction(12, 20); Fraction f3 = new Fraction(f2);
Look at the implementations of the constructors. The two-parameter constructor is straightforward. It assigns the parameters to the numerator and denominator fields. The constructor with one int parameter uses this syntax:
this(n, 1);
The effect of this statement is to call the two-parameter constructor, passing n and 1 as parameters. "this" is a keyword in Java, which normally refers to the object on which a method is invoked. In a constructor, it can be used (as above) to invoke a constructor from within another constructor.
We could have written the one-parameter constructor thusly:
public Fraction(int n) { if (n < 0) {
System.out.println("Fatal error: Negative numerator.");
System.exit(0); }
numberOfFractions++; numerator = n; denominator = 1;
}
Why call the two-parameter constructor instead? The reason is one of good software engineering: by having three of the constructors call the fourth, we have reduced duplicate code--namely, the error-checking code and fraction counting code in the first constructor. By reusing code this way, the program is shorter, and more importantly, if we later find a bug in the constructor, we might only need to fix the first constructor to fix all of them.
This principle applies to methods in general, not just constructors. In your own programs, if you find yourself copying multiple lines of code for reuse, it is usually wise to put the common code into a new shared method.
A. The no-parameter constructor does not use the good style just described. Modify it to callthetwo-parameterconstructor. Then,fillinthefourthconstructorsothatitusesthe good style and correctly duplicates the input Fraction (it does neither now).
B. Further on in the main method, there are four lines commented out. Remove the comment markers and fill in the two missing expressions so that sumOfTwo is the sum of f1 and f2, and sumOfThree is the sum of f0, f1, and f2.
C. The changeNumerator and fracs methods don't work. Fix them. You may NOT change their signatures. Each fix should require the addition of just one word. These changes may or may not be in the methods themselves.
D. The main method prints the Fractions thusly:
System.out.println("The fraction f0 is " + f0.toString()); System.out.println("The fraction f1 is " + f1); // toString is implicit System.out.println("The fraction f2 is " + f2); System.out.println("The fraction f3 is " + f3 + ", which should equal f2");
How does Java know what to do when printing the fractions f1, f2, and f3? In the case of f0, we have invoked the toString method; please read the toString() code.
In the next three lines, we are asking Java to concatenate a Fraction to the end of a String. A Fraction is not a String, so can't be concatenated directly, but Java cleverly looks for a method called toString to convert each Fraction to a string. This is standard in Java: any object can have a toString method, and if it does, that method will be automatically called when you concatenate the object to a String. (Actually, every object has a toString method, but the default toString isn't particularly enlightening.)
As we noted earlier, the toString method prints a Fraction in non-reduced form. Examine the code in the toString method. It is calling another method called gcd that computes the greatest common divisor (GCD) of two positive integers. If this method worked correctly, toString would print Fractions in reduced form; instead, gcd always returns 1. Rewrite the body of gcd so that it is a recursive function that correctly computes the GCD. Recompile and run your program.
Here is pseudocode for a recursive GCD function. a and b must be nonnegative.
function gcd(a, b) if b = 0
return a else
return gcd(b, a mod b)
/* Fraction.java */ import java.io.*; /** The Fraction class implements nonnegative fractions (rational numbers). */ class Fraction { /* private fields within a Fraction. */ private int numberOfFractions = 0; private int numerator; private int denominator; /** Constructs a Fraction n/d. * @param n is the numerator. Must be nonnegative. * @param d is the denominator. Must be positive. */ public Fraction(int n, int d) { if (n < 0) { System.out.println("Fatal error: Negative numerator."); System.exit(0); } if (d < 1) { System.out.println("Fatal error: Nonpositive denominator."); System.exit(0); } numberOfFractions++; numerator = n; denominator = d; } /** Constructs a Fraction n/1. * @param n is the numerator. Must be nonnegative. */ public Fraction(int n) { this(n, 1); } /** Constructs a Fraction 0/1. */ public Fraction() { numberOfFractions++; numerator = 0; denominator = 1; } /** Copies the Fraction "original". */ public Fraction(Fraction original) { numberOfFractions++; numerator = 0; denominator = 1; } /** Converts this Fraction to a string format: "numerator/denominator." * Fractions should be printed in reduced form (part of your assignment is * to make this true). * @return a String representation of this Fraction. */ public String toString() { int thisGcd = gcd(numerator, denominator); return (numerator / thisGcd + "/" + denominator / thisGcd); } /** Return the sum of two fractions. * @param f2 is the Fraction to be added. * @return the result of adding f2 to this Fraction. */ public Fraction add(Fraction f2) { Fraction r = new Fraction((numerator * f2.denominator) + (f2.numerator * denominator), denominator * f2.denominator); return r; } /** Replaces this Fraction's numerator with a new value. * @param numerator is the new numerator. Must be nonnegative. */ public void changeNumerator(int numerator) { // DO NOT CHANGE THIS SIGNATURE! // Fix the bug that prevents this method from working correctly. if (numerator < 0) { System.out.println("Fatal error: Negative numerator."); System.exit(0); } numerator = numerator; } /** Returns the number of Fraction objects in existence. * @return the number of Fraction objects in existence. */ public int fracs() { // DO NOT CHANGE THIS SIGNATURE! // Fix the bug that prevents this method from working correctly. return numberOfFractions; } /** Computes the greatest common divisor (gcd) of the two inputs. * @param x must be nonnegative * @param y must be nonnegative * @return the gcd of x and y */ static private int gcd(int x, int y) { /* Replace the following line with your solution. */ return 1; } /** Put the Fraction class through some tests. * @param argv is not used. */ public static void main(String[] argv) { /* Test all four contructors and toString. */ Fraction f0 = new Fraction(); Fraction f1 = new Fraction(3); Fraction f2 = new Fraction(12, 20); Fraction f3 = new Fraction(f2); System.out.println(" Testing constructors and toString():"); System.out.println("The fraction f0 is " + f0.toString()); System.out.println("The fraction f1 is " + f1); // toString is implicit. System.out.println("The fraction f2 is " + f2); System.out.println("The fraction f3 is " + f3 + ", which should equal f2"); /* Test the add method. */ System.out.println(" Testing add:"); /* Fraction sumOfTwo = _______________; // Sum of f1 and f2. Fraction sumOfThree = ______________; // Sum of f0, f1, and f2. System.out.println("The sum of " + f1 + " and " + f2 + " is " + sumOfTwo); System.out.println("The sum of " + f0 + ", " + f1 + " and " + f2 + " is " + sumOfThree); */ /* Test the methods used in Part III. */ System.out.println(" Testing changeNumerator and fracs:"); f3.changeNumerator(7); System.out.println("Now f3 is " + f3 + ", which should be 7/20"); System.out.println("The total number of Fraction objects is " + f3.fracs()); /* Test gcd function (static method). */ System.out.println(" Testing gcd:"); System.out.println("The gcd of 2 and 10 is: " + gcd(2, 10)); System.out.println("The gcd of 15 and 5 is: " + gcd(15, 5)); System.out.println("The gcd of 24 and 18 is: " + gcd(24, 18)); System.out.println("The gcd of 10 and 10 is: " + gcd(10, 10)); System.out.println("The gcd of 21 and 400 is: " + gcd(21, 400)); } }
Step by Step Solution
There are 3 Steps involved in it
Step: 1
Get Instant Access to Expert-Tailored Solutions
See step-by-step solutions with expert insights and AI powered tools for academic success
Step: 2
Step: 3
Ace Your Homework with AI
Get the answers you need in no time with our AI-driven, step-by-step assistance
Get Started