Cartesian
A.First Edition
This is my first edition of a simple assignment of C++. And I hesitate for some time to decide whether to add it.
Assignment #2 ============= Create a class Fraction which is composed of private "numerator" and "denominator" data members. Your class must contain the following: 1. constructor (including default arguments numerator = denominator = 1) 2. print method (print in the form "numerator/denominator" 3. add function 4. subtract function 5. multiply function 6. divide function * The add, subtract, multiply, and divide functions should be "friends" of the Fraction class. Each function must receive two constant references to Fraction objects as arguments and return a Fraction. Furthermore, these functions must reduce the resulting fraction to the lowest common denominator. * The constructor should also reduce the fraction to the lowest common denominator. (Hint: You may want to write a private function to reduce to the LCD.) * Note that negative fractions are allowed. The negative sign should always be associated with the numerator. ************************************************************************** * Ensure that constant Fraction object may be created, used and printed. * ************************************************************************** * Remember that a denominator should never be zero! Don't forget to handle it! * Document (i.e. comment) your code well!!!!!!! * You MUST use the driver program given below!!!
There is only a few points worth mentioning.
1. How to find LCM? My way is to find GCD and then use theorem that the product of two number is equal to product
of their LCM and GCD. As for GCD, it is very easy to get by Euclidean Algorithm.
2. How to make const objects possible? You must implement all those functions that might be used by const objects
and make sure they are all const. Or in other words, they all have a const key word to make "this" pointer const.
Remember const must also appear in definition of functions.
1. int GCD(int first, int second)
This is another one for Euclidean Algorithm, I remember that at least I implemented it for three times.(including
assembly.)
C.Further improvement
1. All the four friend functions return an object and this implies a dynamic allocated object must be created.
Then who would delete them?
2. Friend functions cannot access member functions of class. And I have to make GCD a friend function either
which is meaningless.
กก
#include <iostream>
using namespace std;
enum FractionName
{Numerator, Denominator};
class Fraction
{
friend Fraction& add(const Fraction& first, const Fraction& second);
friend Fraction& subtract(const Fraction& first, const Fraction& second);
friend Fraction& multiply(const Fraction& first, const Fraction& second);
friend Fraction& divide(const Fraction& first, const Fraction& second);
friend int GCD(int first, int second);
private:
int denominator;
int numerator;
void reduceForm();
public:
void print() const;
Fraction(int num=1, int den=1);
};
int main()
{
Fraction F;
// TEST ZERO DEMONINATOR
Fraction f0(1,0) ; // uh-oh! constructor should handle it
cout << "Fraction f0(1,0) = " ;
f0.print() ; //should NOT print "1/0"
cout << endl ;
// TEST REDUCE LOWEST COMMON DENOMINATOR
Fraction f1(2,6) ; // should reduce to 1/3
cout << "Fraction f1(2,6) = " ;
f1.print() ; // should print "1/3"
cout << endl ;
Fraction f2(1024,8) ; // reduces to 128/1
cout << "Fraction f2(1024,8) = " ;
f2.print() ; // should print "128"
cout << endl ;
// TEST NEGATIVE FRACTION
Fraction fneg(3,-7) ;
cout << "Fraction fneg(3,-7) = " ;
fneg.print() ; // should print "-3/7"
cout << endl ;
// TEST const FRACTION CREATION
const Fraction half(1,2) ;
cout << "const Fraction half(1,2) = " ;
half.print() ; // should print "1/2"
cout << endl ;
// TEST ADD FUNCTION
Fraction Fa ; // defaults to 1/1
Fa = add( f1, f2 ) ; // memberwise copy
cout << "Fa = add( f1, f2 ) = " ;
Fa.print() ; // should print "385/3"
cout << endl ;
cout << "add( f1, half ).print() = " ;
add( f1, half ).print() ; // should print "5/6"
cout << endl ;
// TEST SUBTRACT FUNCTION
cout << "subtract( half, fneg ).print() = " ;
subtract( half, fneg ).print() ; // should print "13/14"
cout << endl ;
cout << "subtract( f1, Fa ).print() = " ;
subtract( f1, Fa ).print() ; // should print "-128"
cout << endl ;
// TEST MULTIPLY FUNCTION
cout << "multiply( f1, fneg ).print() = " ;
multiply( f1, fneg ).print() ; // should print "-1/7"
cout << endl ;
// TEST DIVIDE FUNCTION
cout << "divide( f1, fneg ).print() = " ;
divide( f1, Fa ).print() ; // should print "1/385"
cout << endl ;
return 0;
}
//denominator may be input 0 or negative, which should be handled
Fraction::Fraction(int num, int den)
{
numerator = num;
if (den==0)
{
cout<<"uh-oh!Denominator is 0! And it is set to 1 now.\n";
denominator = 1;
}
else
{
//I need to keep denominator to be positive always
if (den<0)
{
denominator = den*(-1);
numerator *= -1;//the sign should be carried by numerator
}
else
{
denominator = den;
}
}
reduceForm();
}
//I need to find the GCD which must be positive
void Fraction::reduceForm()
{
int divisor;
//the divisor must be positive
divisor = GCD(abs(numerator), denominator);
if (divisor!=1)
{
numerator /= divisor;
denominator /= divisor;
}
}
void Fraction::print() const
{
cout<<(numerator<0?'-':' ')<<abs(numerator)<<'/'<<denominator<<endl;
}
//Using Euclidean Algorithms to find GCD
int GCD(int first, int second)
{
div_t result; //this is a built-in struct
int divider = first;
int divisor = second;
result = div(divider, divisor);
while (result.rem!=0)
{
divider = divisor;
divisor = result.rem;
result = div(divider, divisor);
}
return divisor;
}
Fraction& add(const Fraction& first, const Fraction& second)
{
int gcd, lcm;
int newNum;
gcd = GCD(first.denominator, second.denominator);
//a theorem: product of two number equal product of their GCD and LCM
lcm = first.denominator * second.denominator / gcd;
newNum = lcm / first.denominator * first.numerator;
newNum += lcm/second.denominator * second.numerator;
Fraction* Result = new Fraction (newNum, lcm);
return *Result;
}
Fraction& subtract(const Fraction& first, const Fraction& second)
{
int gcd, lcm;
int newNum;
gcd = GCD(first.denominator, second.denominator);
//a theorem: product of two number equal product of their GCD and LCM
lcm = first.denominator * second.denominator / gcd;
newNum = lcm / first.denominator * first.numerator;
newNum -= lcm/second.denominator * second.numerator;
Fraction* Result = new Fraction(newNum, lcm);
return *Result;
}
Fraction& multiply(const Fraction& first, const Fraction& second)
{
Fraction* Result =
new Fraction(first.numerator*second.numerator, first.denominator*second.denominator);
return *Result;
}
Fraction& divide(const Fraction& first, const Fraction& second)
{
Fraction* Result =
new Fraction (first.numerator*second.denominator, first.denominator*second.numerator);
return *Result;
}