CIT 591 Assignment 7: Fractions
Fall 2009, David Matuszek
Implement a Fraction
API. Write very thorough
JUnit tests. Write a small "calculator" program to do arithmetic with fractions.
Create a project named Fraction
, and within that, a package named fraction
. Your classes, Fraction
, FractionTest
, and FractionCalculator
, will all be within this package.
Declare your class as public class Fraction implements Comparable {...}
. (The reason for the "implements" part will be explained in class; for now, just do it.)
Java provides several types of numbers, but it does not provide fractions. Your task is to implement a Fraction
API, and write a small program that uses it.
The following table lists some information about your new Fraction
type.
Instance variables | Two Note: Even though these instance variables are |
---|---|
How written | n/d , where n is the numerator and d
is the denominator. |
Restrictions | The denominator may not be zero. |
Normalization | • The fraction is always kept in the lowest terms, that is, the Greatest
Common Divisor (GCD) of n and d is 1
(use Euclid's algorithm).• The denominator is never negative. (You can give a negative number for the denominator to the constructor when you create the fraction, but a negative fraction should be represented internally with a negative numerator.) • Zero should be represented as 0/1. |
The following lists the consructors you should have.
Constructor | How it uses its parameters |
---|---|
public Fraction(int numerator, int denominator) |
Parameters are the numerator and the denominator. Normalize the fraction as you create it. For instance, if the parameters are (8, -12) , create a Fraction with numerator -2 and denominator 3 . The constructor should throw an ArithmeticException if the denominator is zero. |
public Fraction(int wholeNumber) |
The parameter is the numerator and 1 is the implicit denominator. |
public Fraction(String fraction) |
The parameter is a You may find it helpful to look at the available String methods in the Java API. |
Notes:
new Fraction(3)
you will get the second constructor listed above. A String is a String, though, so the third constructor will have to distinguish between "3"
and "3/4"
.throw new ArithmeticException("Divide by zero");
(The String parameter is optional.)Integer(string).parseInt()
will return the int
equivalent of the string
(assuming that the string
represents a legal integer).Method signature | What it does |
---|---|
public Fraction add(Fraction f) |
Returns a new Fraction that is the sum of this and that : a/b + c/d is (ad + bc)/bd |
public Fraction subtract(Fraction f) |
Returns a new Fraction that is the difference of this minus that :a/b - c/d is (ad - bc)/bd |
public Fraction multiply(Fraction f) |
Returns a new Fraction that is the product of this and that :(a/b) * (c/d) is (a*c)/(b*d) |
public Fraction divide(Fraction f) |
Returns a new Fraction that is the quotient of dividing this by that :(a/b) / (c/d) is (a*d)/(b*c) |
public Fraction abs() |
Returns a new Fraction that is the absolute value of this fraction. |
public Fraction negate() |
Returns a new Fraction that has the same numeric value of this fraction, but the opposite sign. |
public Fraction inverse() |
The inverse of a/b is b/a. |
@Override |
Returns true if o is a Fraction equal to this , and false in all other cases.You need this method for your assertEquals(expected, actual) JUnit tests to work! The assertEquals method calls your equals method to do its testing. |
@Override |
If o is a |
@Override |
Returns a |
Notes:
Fraction
s should be immutable, that is, there should be no way to
change their components after the numbers have been created. Most of your methods
simply return a new number.equals
, notice that it
requires an Object
as a parameter. This means that the first thing
the method should do is make sure that its parameter is in fact a Fraction
,
and return false
if it is not.
o instanceof Fraction
. o
as a Fraction
by saying ((Fraction)o)
, or you can save it in a Fraction
variable by saying Fraction f = (Fraction)o;
and then using f
. public
, but do test them (if you can figure out how). To put a fraction into its lowest terms, divide both the numerator and the
denominator by their Greatest Common Divisor (GCD). Euclid's algorithm
finds the GCD of two integers. It works as follows: As long as the two numbers
are not equal, replace the larger number with the remainder of dividing the
larger by the smaller (that is,
).
When the two numbers are equal, that value is the GCD. (If this brief explanation
isn't enough, look up Euclid's algorithm on the Web.)
Your goal in writing the JUnit class is to test for every possible
error. This includes making sure that the correct Exception
s are
thrown when appropriate.
Most of your tests will have this form:
@Test
public void testAdd() { // Tests that are expected to succeed }
To test for an exception, use this form:
You can find the various kinds of assertions you can make in the JUnit API.@Test(expected=ArithmeticException.class)
public void testDivideByZero() { // test that should throw an ArithmeticException }
Write a FractionCalculator
class (containing a main
method) that does calculations with Fractions. The first thing this program does is print a zero (indicating the current contents of the calculator), and a prompt. It then accepts commands from the user, and after each command, prints the result. Here are the commands it should accept:
c
To clear (reset to zero) the calculator.q
To quit the program.+ n
To add n
to the number currently displayed.- n
To subtract n
from the number currently displayed.* n
To multiply the number currently displayed by n
./ n
To divide the number currently displayed by n
.In each case, the user may enter either a whole number or a fraction for n
.
As this class does little computation on its own (it's all done in the Fraction
class), and is mostly concerned with input/output, no unit testing is necessary.
You will need to use the Scanner
. You can find a brief description in my From Python to Java page, and a much longer description (skip over the confusing details) in the Scanner page in the Java API.
Recommendation: Just use the Scanner's readLine()
method, and use String methods to work with the input. Some useful methods are trim()
, length()
, and substring(beginIndex)
. I found this somewhat easier that working with the Scanner methods.
All methods in your Fraction
and FractionCalculator
class should have Javadoc comments. The methods in your test class do not need to be commented, unless they are particularly complex or non-obvious.
Eclipse can help you by writing the Javadoc "outline" for you, which you can fill in. For example, suppose you have written the method stub (you are using TDD, aren't you?):
public Fraction add(Fraction f) {
return null;
}
Place your cursor in the method and choose Source -> Generate Block Comment (or hit Ctrl-Alt-J). Eclipse creates the comment
/**
* @param f
* @return
*/
which you can then fill in, as for example:
/** * Returns the sum of this Fraction and the Fraction f.
* @param f The Fraction to be added to this one.
* @return The sum of the two Fractions.
*/
Your grade will be based on:
We will use our own programs and our own unit tests for grading purposes--therefore, you must have method names and parameter types exactly as shown.
Thursday, October 7 Friday, November 6, before midnight.