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; }