Sample Solutions to Homework 2

Summary: Here you will find some sample solutions to the exercises from Homework 2.

Contents

Solutions To Exercises

Exercise 1: Multiplication

a. Extend the `Fraction` class so that it permits multiplication of two fractions.

```  /**
* Multiply this fraction by another fraction.
*/
public Fraction multiply(Fraction other)
{
// a/b * c/d = (a*c)/(b*d)
return new Fraction(this.numerator.multiply(other.numerator),
this.denominator.multiply(other.denominator));
} // multiply(Fraction)
```

i. Using the original fractions:

```3/10 * 2/5 = 6/50
```

Hmmm ... perhaps I should simplify.

ii. Using fractions whose product should be 1.

```1/3 * 3/1 = 3/3
```

iii. Using a variety of negative fractions.

```-1/4 * 3/11 = -3/44
1/4 * -3/11 = -3/44
-1/4 * -3/11 = 3/44
```

Seems okay.

iv. Using some really big numerators and denominators

```1111111111/4 * 1111111111/11 = 1234567900987654321/44
4123/1111111111 * 11/1111111111 = 45353/1234567900987654321
```

Still seems fine. (Yeah, I should have chosen something easier to check.)

Exercise 2: Fractional Portions

As you may know, we can represent every non-negative rational number as a whole number plus a fractional value no smaller than 0 and no bigger than 1.

a. Write a method of the `Fraction` class, `fractional`, that identifies and returns this fractional value. Your procedure need only work for positive numbers.

For example,

```Fraction f = new Fraction(11,3);
pen.println(f.fractional());
// Prints 2/3
f = new Fraction(1,2);
pen.println(f.fractional());
// Prints 1/2
f = new Fraction(4,2);
pen.println(f.fractional());
// Prints 0/2 or something similar
```

Well, to find the fractional part, what I really want is the remainder when I divide the numerator by the denominator. I can then return the ratio of that remainder and the denominator.

A quick check of the documentation reveals that BigInteger helpfully provides a `remainder(BigInteger divisor)` method, so I can just use that.

```  /**
* Compute the fractional part of the fraction.  That is, if we
* think of the fraction n/d as (a*d+b)/d, where 0 <= b < d,
* returns d/b.
*/
public Fraction fractional()
{
return new Fraction(numerator.remainder(this.denominator),this.denominator);
} // fractional()
```

I'll try four tests: (i) a fraction with no whole part, (ii) a fraction with no fractional part, (iii) a fraction with a small whole part, and (iv) a fraction with a large whole part.

```The fractional part of 1/3 is 1/3
The fractional part of 6/3 is 0/3
The fractional part of 12/5 is 2/5
The fractional part of 1231152344523342/10 is 2/10
```

Exercise 3: From String to Fraction

Write and test a third constructor for the `Fraction` class. This constructor should accept a string as a parameter, parse that string, and generate the appropriate fraction. For example,

```Fraction f = new Fraction("1/4");
pen.println(f.doubleValue());
// Prints 0.25
f = new Fraction("120/3");
pen.println(f.doubleValue());
// Prints 40.0
```

You can expect that the string will have two positive integers separated by a slash. You may find it useful to reflect on the `indexOf` method of the `java.lang.String` class and on various methods of the `java.lang.Integer` class.

To convert a string of the form "num/denom" to the appropriate fields, it seems that I need to figure out two things: (i) how to separate the big string into two smaller strings (one for the numerator and one for the denominator) and (ii) how to convert each string into a BigInteger.

We've looked at the problem of separating strings in the past, so that part should be fairly straightforward. We identify the position of the separator (the slash) and take the stuff before it and the stuff after it.

The problem of converting strings to BigIntegers should only require a quick check of the documentation. Amazingly enough, although BigInteger does not provide a constructor that takes an `int` as a parameter, it does provide a constructor that takes a string.

Putting it all together,

```  /**
* "Parse" a string of the form "numerator/denominator" to
* a Fraction.
*/
public Fraction(String description)
{
// Determine the position of the slash
int slash = description.indexOf("/");
// Grab the numerator
String num = description.substring(0,slash);
// Grab the denominator
String denom = description.substring(slash+1);
// Convert to BigIntegers
this.numerator = new BigInteger(num);
this.denominator = new BigInteger(denom);
} // Fraction(String)
```

We might also express this more concisely as,

```  public Fraction(String description);
{
// Determine the position of the slash
int slash = description.indexOf("/");
// Build the two fields
this.numerator = new BigInteger(description.substring(0,slash));
this.denominator = new BigInteger(description.substring(slash+1));
} // Fraction(String)
```

Exercise 4: A Simple Calculator

Write a main class that reads in two fractions and prints out their sum and product in both fractional and decimal form.

See Calculator.java.

Exercise 5: A Counter Class

Write and test a class, `Counter`, that generates objects that can count. Objects in class `Counter` should provide two methods: `increment`, which adds 1 to the counter, and `get`, which gets the current value of the counter.

Make sure to verify that if you create two separate objects in class `Counter`, you can change the two objects separately.

`Counter` objects will have one field, `count`, which is an `int`. `increment` adds one to the field. `get` returns the field. The one constructor will take no parameters and set the counter to 0.

See the details in Counter.java.

Here are some tests that suggest the two counters work independently

```Initially ...
c1 = 0, c2 = 0
After incrementing c1 ...
c1 = 1, c2 = 0
After incrementing c2 three times ...
c1 = 1, c2 = 3
After incrementing c1 again ...
c1 = 2, c2 = 3
```

Exercise 6: Extending Counters

a. Update your `Counter` class to include a second constructor that Allows the user to specify a starting value.

b. Update your `Counter` class to include a `reset` method that reset the counter to the starting value.

Although I expected you to update `Counter.java`, I've made a second class, which I've called `ExtendedCounter.java`.

The key implementation details have to do with resetting. Since we have to reset to the starting value, we need to add a field to keep track of that value. I'll call that field `start`. Reset simply sets `count` to `start`.

See the details in ExtendedCounter.java.

Here are some tests that show that we can create counters that start at 0, at a positive number, and at a negative number; that those counters increment independently; that those counters reset correctly and independently; and that increment continues to work after the reset.

```Initially ...
c1=0, c2=5, c3=-3
After incrementing c1 ...
c1=1, c2=5, c3=-3
After incrementing c2 three times ...
c1=1, c2=8, c3=-3
After incrementing c1 again ...
c1=2, c2=8, c3=-3
After incrementing c3 twice ...
c1=2, c2=8, c3=-1
After resetting c1 ...
c1=0, c2=8, c3=-1
After incrementing c1 again ...
c1=1, c2=8, c3=-1
After resetting c2 ...
c1=1, c2=5, c3=-1
After incrementing c2 again ...
c1=1, c2=6, c3=-1
After resetting c3 ...
c1=1, c2=6, c3=-3
After incrementing c2 again ...
c1=1, c2=6, c3=-2
After incrementing c2 again ...
c1=1, c2=7, c3=-2
```

History

Sunday, 25 September 2005 [Samuel A. Rebelsky]

Wednesday, 28 September 2005 [Samuel A. Rebelsky]

This document may be found at `http://www.cs.grinnell.edu/~rebelsky/Courses/CS152/2005F/Homework/soln.02.html`.