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.
B.The problem
	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!!!
C.The idea of program
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.
D.The major 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;
}





                                 back.gif (341 bytes)       up.gif (335 bytes)         next.gif (337 bytes)

Hosted by www.Geocities.ws

1