CS 12 - Assignment 4 - Rational Numbers


CS 12 Homepage

Due via e-turnin by Saturday 4/24, 11pm


Collaboration Policy:
Collaboration on home programming assignments is strictly FORBIDDEN.
Programs must represent YOUR OWN original work.
Sharing code or team-coding are not allowed. Copying code from ANY source (any book, current or past students, past solutions, the web, etc.) is not allowed.
Cooperation to the extent of helping to debug, or discussing the general approach to solving the problem is encouraged, but should never involve communicating code or even pseudo-code or explicit algorithms. Your code must be unique.


Fractions, aka Rational Numbers


Read Problem 9, chap. 6 (p. 380) for the full specification of this assignment

It may come as a bit of a surprise when the C++ floating-point types (float, double), fail to accurately capture a particular value. Certainly double, which is usually stored as a 64-bit value, is far better than the old float, which is only 32 bits, but problems do arise. For example:
float n = 2.0;
float d = 3.0;
cout.precision(17);
cout << n / d << endl;
Produces 0.66666668653488159, which is accurate to 8 decimal places. Not bad, but a bit dirty for a discipline that prides itself on precision.

A solution that is often used when precision is of greatest importance and all of the numbers involved are going to be rational (that is, expressible as a fraction) is to use a custom type that implements fractions / rational numbers. This is what you will do in this assignment.

The spec


Write a C++ program that performs the rational number operations addition, subtraction, multiplication, division, less than, and equals operations on two fractions.
You will have to design a rational number class whose value will be a fraction (e.g. 1/128, or 22/7), with appropriate constructors, accessor and mutator functions. A fraction will be specified as a numerator and a denominator - e.g. the pair (8, 109) represents the fraction 8/109.
Your program must implement the rational number operations listed above, and test both the class and the operations thoroughly.

You need to use constructors for:
    1) correctly initializing member variables, and
    2) creating objects with given initial values.

Note that a fraction may have both a numerator and a denominator, for example: (8/3), or may simply be a number, for example: 6, in which case you will actually use (6/1) to represent it.  Thus, the constructors with two and one arguments should be included in the class definition.
Question: what would be a useful default constructor - i.e. what would you consider to be the null Rational Number?

Your program will have a function for each one of the six operations add, sub, mul, div, less, equals.
For example: Suppose we have defined objects a and b as two fractions, then to compute a + b, we will use:

a.add(b);

When you perform an operation, you do not have to simplify the result, i.e., 4/5 * 5/10 = 20/50.

Here are the rules you will need:

(a/b) + (c/d) = (a*d + b*c) / (b*d)

(a/b) - (c/d) = (a*d - b*c) / (b*d)
(a/b) * (c/d) = (a*c) / (b*d)
(a/b) / (c/d) = (a*d) / (c*b)
(a/b) < (c/d) => (a*d) < (c*b)
(a/b) == (c/d) => (a*d) == (c*b)

Extra credit (1 point)

Extend your class and operator functions to properly handle either positive or negative rational numbers, including the case of both numerator and denominator being negative.