Homework 6
Skills needed to complete this assignment:
-
Creating classes and using object-oriented program design (lecture notes)
-
Splitting code into several files (lecture notes)
(See the Complex class on Classes and object orientation page for an example that is similar to this assignment.)
Write a rational number class. This problem is revisited in Chapter 11
(in the book), where operator overloading will make the problem much
easier. For now we will use member functions add, sub, mul,
div, and less that each carry out the operations +, -, *,
/, and <. For example, a+b will be written a.add(b), and a<b
will be written a.less(b).
Define a class for rational numbers. A rational number is a
“ratio-nal” number, composed of two integers with division
indicated. The division is not carried out, it is only indicated, as
in 1/2, 2/3, 15/32, 65/4, 16/5. You should represent rational numbers
by two int values, numerator and denominator.
We want to store rational numbers in canonical form, meaning the rational number 9/12 would be stored as 3/4 and 25/5 would be stored as 5/1. This is discussed more below.
A principle of abstract data type construction is that constructors
must be present to create objects with any legal values. You should
provide constructors to make objects out of pairs of int values
(i.e. a constructor with two int parameters). Since every int is
also a rational number, as in 2/1 or 17/1, you should provide a
constructor with a single int parameter, which just sets the
numerator to the value of the parameter and the denominator to 1.
Provide member functions add, sub, mul, and div that return
a rational value (each of these functions has a single rational
parameter). Provide a function less that has a single rational
parameter and returns a bool value. These functions should do the
operation suggested by the name (e.g. num1.less(num2) returns true
if the rational number num1 is less than the rational number
num2). Provide a member function neg that has no parameters and
returns a rational number that is the negative of the calling object.
*For the second part, use operator overloading to implement add (+), sub (-), mul (*), div (/), less (<) and neg (-). *
Also provide a member function print that simply prints the rational
number in a format like -9/13.
Each of these member functions should return a different instance of
the class. So once you have an instance of the class, you cannot
change its values (rationals will be “immutable”). For example, here
is what the add function header looks like:
Rational add(Rational &other)
{
int n, d;
n = ...
// ...
return Rational(n, d); // return a different rational number
}The function above can be understood in the following way. The add
function is a member function of class Rational (because it will be
somewhere inside the class definition, which is not shown here), and
it receives as its single parameter a reference to an instance of the
same class (which we call other in the function). We make it a
reference parameter (“call-by-reference”) to make the function call
more efficient (the instance other need not be copied when the
function is called).
To repeat, inside the add function, you’ll make an instance of the
Rational class and set its values. Then you return that instance.
Always store and print the reduced form of the rational number; that
is, always divide out the greatest common divisor (GCD) of the
numerator and denominator. C++ code for finding the GCD is abundant on
the internet;
here is one
example. I recommend you make a gcd function that’s not a member
function, that only has two integers as its parameters, and that
returns an integer.
Some advice: Use the GCD function in the constructor that has two
inputs (numerator and denominator); only use the GCD function
here. Then, like the code example above, every other function
(e.g. add, div, etc.) should call the constructor. That way, every
function returns a reduced form of the answer.
Provide a main function that thoroughly tests your class
implementation (write a little test for each of the functions).
The following formulas will be useful in defining functions.
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) = (-a/b)
(a/b) < (c/d) means (a*d) < (c*b)
(a/b) == (c/d) means (a*d) == (c*b)Keep any negative sign in the numerator; keep the denominator positive. (So 5/-2 should be saved as -5/2.)
Finally, you must split your code into three files (exactly these files):
-
rational.hwhich contains the class declaration -
rational.cppwhich contains the class functions -
main.cppwhich contains testing code (i.e. themain()function)
Submit to me all three files (in a ZIP file).