package ps1; import junit.framework.TestCase; /** This class contains a set of test cases that can be used to test the implementation of the RatNum class.
RatNum is implemented for you, so it should already pass all the
tests in this suite. This test is provided to give you examples
of using the RatNum class, albeit in the context of a test driver.
*/
public class RatNumTest extends TestCase {
// naming convention used throughout class: spell out number in
// variable as its constructive form. Unary minus is notated with
// the prefix "neg", and the solidus is notated with an 'I'
// character. Thus, "1 + 2/3" becomes one_plus_two_I_three
// some simple base RatNums
private RatNum zero = new RatNum(0);
private RatNum one = new RatNum(1);
private RatNum negOne = new RatNum(-1);
private RatNum two = new RatNum(2);
private RatNum three = new RatNum(3);
private RatNum one_I_two = new RatNum(1, 2);
private RatNum one_I_three = new RatNum(1, 3);
private RatNum one_I_four = new RatNum(1, 4);
private RatNum two_I_three = new RatNum(2, 3);
private RatNum three_I_four = new RatNum(3, 4);
private RatNum negOne_I_two = new RatNum(-1, 2);
// improper fraction
private RatNum three_I_two = new RatNum(3, 2);
// NaNs
private RatNum one_I_zero = new RatNum(1, 0);
private RatNum negOne_I_zero = new RatNum(-1, 0);
private RatNum hundred_I_zero = new RatNum(100, 0);
// ratnums: Set of varied ratnums (includes NaNs)
// set is { 0, 1, -1, 2, 1/2, 3/2, 1/0, -1/0, 100/0 }
private RatNum[] ratnums = new RatNum[] {
zero, one, negOne, two, one_I_two, negOne_I_two, three_I_two,
/* NaNs */ one_I_zero, negOne_I_zero, hundred_I_zero
};
// ratnans: Set of varied NaNs
// set is { 1/0, -1/0, 100/0 }
private RatNum[] ratnans = new RatNum[] {
one_I_zero, negOne_I_zero, hundred_I_zero
};
// ratnanans: Set of varied non-NaN ratnums
// set is ratnums - ratnans
private RatNum[] ratnanans = new RatNum[] {
zero, one, negOne, two, one_I_two, three_I_two
};
public RatNumTest(String name) { super(name); }
// self-explanatory helper function
private void eq( RatNum ratNum, String rep ) {
assertEquals( rep, ratNum.unparse() );
}
public void testOneArgCtor() {
eq( zero, "0" );
eq( one, "1" );
RatNum four = new RatNum(4);
eq( four, "4" );
eq( negOne, "-1" );
RatNum negFive = new RatNum(-5);
eq( negFive, "-5" );
RatNum negZero = new RatNum(-0);
eq( negZero, "0" );
}
public void testTwoArgCtor() {
RatNum one_I_two = new RatNum(1, 2);
eq( one_I_two, "1/2" );
RatNum two_I_one = new RatNum(2, 1);
eq( two_I_one, "2" );
RatNum three_I_two = new RatNum(3, 2);
eq( three_I_two, "3/2" );
RatNum negOne_I_thirteen = new RatNum(-1, 13);
eq( negOne_I_thirteen, "-1/13" );
RatNum fiftyThree_I_seven = new RatNum(53, 7);
eq( fiftyThree_I_seven, "53/7" );
RatNum zero_I_one = new RatNum(0, 1);
eq( zero_I_one, "0" );
}
public void testTwoArgCtorOnNaN() {
RatNum one_I_zero = new RatNum(1, 0);
eq( one_I_zero, "NaN" );
RatNum two_I_zero = new RatNum(2, 0);
eq( two_I_zero, "NaN" );
RatNum negOne_I_zero = new RatNum(-1, 0);
eq( negOne_I_zero, "NaN" );
RatNum zero_I_zero = new RatNum(0, 0);
eq( zero_I_zero, "NaN" );
RatNum negHundred_I_zero = new RatNum(-100, 0);
eq( negHundred_I_zero, "NaN" );
}
public void testReduction() {
RatNum negOne_I_negTwo = new RatNum(-1, -2);
eq( negOne_I_negTwo, "1/2" );
RatNum two_I_four = new RatNum(2, 4);
eq( two_I_four, "1/2" );
RatNum six_I_four = new RatNum(6, 4);
eq( six_I_four, "3/2" );
RatNum twentySeven_I_thirteen = new RatNum(27, 13);
eq( twentySeven_I_thirteen, "27/13" );
RatNum negHundred_I_negHundred = new RatNum(-100, -100);
eq( negHundred_I_negHundred, "1" );
}
// self-explanatory helper function
private void approxEq(double d1, double d2) {
assertTrue (Math.abs(d1 - d2) < .0000001);
}
public void testApprox() {
approxEq( zero.approx(), 0.0 );
approxEq( one.approx(), 1.0 );
approxEq( negOne.approx(), -1.0 );
approxEq( two.approx(), 2.0 );
approxEq( one_I_two.approx(), 0.5 );
approxEq( two_I_three.approx(), 2./3. );
approxEq( three_I_four.approx(), 0.75 );
// cannot test that one_I_zero.approx() approxEq Double.NaN,
// because it WON'T!!! Instead, construct corresponding
// instance of Double and use .equals(..) method
assertTrue( (new Double(Double.NaN)).
equals
(new Double(one_I_zero.approx())) );
// use left-shift operator "<<" to create integer for 2^30
RatNum one_I_twoToThirty = new RatNum(1, (1<<30) );
double quiteSmall = 1./Math.pow(2, 30);
approxEq( one_I_twoToThirty.approx(), quiteSmall );
}
public void testAddSimple() {
eq( zero.add(zero), "0" );
eq( zero.add(one), "1" );
eq( one.add(zero), "1" );
eq( one.add(one), "2" );
eq( one.add(negOne), "0" );
eq( one.add(two), "3" );
eq( two.add(two), "4" );
}
public void testAddComplex() {
eq( one_I_two.add(zero), "1/2" );
eq( one_I_two.add(one), "3/2" );
eq( one_I_two.add(one_I_two), "1" );
eq( one_I_two.add(one_I_three), "5/6" );
eq( one_I_two.add(negOne), "-1/2" );
eq( one_I_two.add(two), "5/2" );
eq( one_I_two.add(two_I_three), "7/6" );
eq( one_I_two.add(three_I_four), "5/4" );
eq( one_I_three.add(zero), "1/3" );
eq( one_I_three.add(two_I_three), "1" );
eq( one_I_three.add(three_I_four), "13/12" );
}
public void testAddImproper() {
eq( three_I_two.add(one_I_two), "2" );
eq( three_I_two.add(one_I_three), "11/6" );
eq( three_I_four.add(three_I_four), "3/2" );
eq( three_I_two.add(three_I_two), "3" );
}
public void testAddOnNaN() {
// each test case (addend, augend) drawn from the set
// ratnums x ratnans
for(int i=0; i