Fraction Library
A C++ Fraction library.

MFraction.cpp

Go to the documentation of this file.
00001 
00007 #include "MFraction.h"
00008 
00009 #ifndef FRACTION_ONLY   
00010 
00011         #include <string>       
00012 
00013         /**************** INITIALIZES DEFAULT MFRACTION FORMAT BEHAVIOUR ****************/
00014 
00015         MFraction::FracFormat MFraction::FORMAT = MIX_FRAC;
00016 
00017         /******************* DEFINES FORMAT ACCESSOR/MUTATOR METHODS *******************/
00018 
00019         //this method sets the fraction format (how the fraction is to be outputed)
00020         void MFraction::setFormat(const MFraction::FracFormat &format)
00021         {
00022                 FORMAT = format;
00023         }
00024 
00025         //this method returns the fraction format (how the fraction is being outputed)
00026         MFraction::FracFormat MFraction::getFormat()
00027         {
00028                 return (FORMAT);
00029         }
00030 
00031         /*********************** HELPER METHODS PRIVATE TO CLASS ***********************/
00032 
00033         //reduces the improper version of the fraction created by Fraction class's reduce() method into a mixed fraction
00034         void MFraction::reduce()
00035         {
00036                 //Fraction class's reduce() method is called already when Fraction constructor is called
00037                 //or when Fraction's classes operations (+,- etc.) are called.
00038                 if (numerator >= denominator)
00039                 {
00040                         whole += numerator/denominator;
00041                         numerator %= denominator;
00042                 }
00043         }
00044 
00045         /*************************** CONSTRUCTORS/DESTRUCTORS **************************/
00046 
00047         //default constructor: sets fraction to 0
00048         MFraction::MFraction() : Fraction()
00049         {
00050                 whole = 0;
00051         }
00052 
00053         //constructor converts a decimal number into a fraction
00054         //accuracy roughly around 3-4 decimal places
00055         MFraction::MFraction(const double &number) : Fraction(number)
00056         {              //Fraction class's reduce() method runs before code below executes
00057                 whole = 0;
00058                 reduce();  //convert fraction into reduced mixed representation by calling MFraction's reduce()
00059         }
00060 
00061         //takes numerator and denominator of fraction (not reduced) and creates a reduced mixed fraction
00062         MFraction::MFraction(const int &numerator, const int &denominator) : Fraction(numerator,denominator)
00063         {
00064                 whole = 0;
00065                 reduce();
00066         }
00067 
00068         //takes whole, numerator and denominator of fraction (not reduced) and creates a reduced mixed fraction
00069         MFraction::MFraction(const int &whole, const int &numerator, const int &denominator) : Fraction(numerator,denominator)
00070         {
00071                 if (whole < 0) sign = !sign;
00072                 this->whole = abs(whole);
00073                 reduce();
00074         }
00075 
00076         //converts a valid character array into a fraction
00077         MFraction::MFraction(const char *frac)
00078         {
00079                 //convert the character array into a string
00080                 string fraction = frac;
00081 
00082                 //if the string parameter has any characters other than "-0123456789./", it is invalid
00083                 if (fraction.find_first_not_of("-0123456789./")!=-1)
00084                         throw (FR_STR_INVALID);
00085 
00086                 //find position of the decimal place, if present
00087                 int pos = fraction.find_first_of(".");
00088 
00089                 if (pos!=-1)                                       //if a decimal place is present
00090                 {   //check that all other characters are numbers only
00091                         if (fraction.find_first_of("/")==-1 && fraction.find_first_of(".",pos+1)==-1)
00092                                 *this = MFraction(atof(fraction.c_str())); //if so, create a MFraction object
00093                         else
00094                                 throw (FR_STR_INVALID);                       //otherwise, string is invalid
00095                 }
00096                 else
00097                 {
00098                         pos = fraction.find_first_of("/");               //if there was no decimal place, look for a slash
00099 
00100                         if (pos==-1)                                     //if there is no / at all, ie. "5"
00101                                 *this = MFraction(atoi(fraction.c_str()));
00102                         else                                              //if one slash was found
00103                         {
00104                                 int pos2 = fraction.find_first_of("/",pos+1); //look for a second slash
00105 
00106                                 if (pos2==-1)                                 //if there is no second slash
00107                                         *this = MFraction(atoi(fraction.substr(0,pos).c_str()),atoi(fraction.substr(pos+1,fraction.length()-pos-1).c_str()));
00108                                 else if (fraction.find_first_of("/",pos2+1)==-1)  //if there is no third slash, but there is a 2nd one
00109                                         *this = MFraction(atoi(fraction.substr(0,pos).c_str()),atoi(fraction.substr(pos+1,pos2-pos-1).c_str()),atoi(fraction.substr(pos2+1,fraction.length()-pos2-1).c_str()));
00110                                 else
00111                                         throw (FR_STR_INVALID);                       //otherwise, string is invalid
00112                         }
00113                 }
00114         }
00115 
00116         //copy constructor: copies another fraction (of type Fraction) into the created fraction
00117         MFraction::MFraction(const Fraction &frac) : Fraction(frac)
00118         {
00119                 whole = 0;
00120                 reduce();
00121         }
00122 
00123         //copy constructor: copies another fraction (of type MFraction) into the created fraction
00124         MFraction::MFraction(const MFraction &frac) : Fraction(frac)
00125         {
00126                 whole = frac.whole;
00127         }
00128 
00129         //destructor: does nothing as there are no dynamic memory
00130         //the data members are deallocated automatically
00131         MFraction::~MFraction()  //destructor for Fraction is called auto after this
00132         {
00133         }
00134 
00135         /******************************* MUTATOR METHODS *******************************/
00136 
00137         //sets the whole number portion of the fraction
00138         void MFraction::setWhole(int whole)
00139         {               
00140                 sign = whole >= 0;
00141                 this->whole = abs(whole);
00142         }
00143         
00144         //sets the numerator of the fraction
00145         void MFraction::setNum(int numerator)
00146         {
00147                 Fraction::setNum(numerator);
00148                 reduce();
00149         }
00150 
00151         //sets the denominator of the fraction
00152         void MFraction::setDen(int denominator)
00153         {
00154                 Fraction::setDen(denominator);
00155                 reduce();
00156         }
00157 
00158         /**************************** OVERLOADED OPERATORS *****************************/
00159 
00160         //the subscript operator must be a member function
00161         //pass in 0 to get whole (signed), 1 for numerator (signed), 2 for denominator (unsigned)
00162         int MFraction::operator [] (const unsigned int &subscript) const
00163         {
00164                 if (subscript > 2) throw (FR_INDEX_OUT_BOUNDS);
00165 
00166                 if (subscript == 0)
00167                 {
00168                         if (sign) return (whole);
00169                         else return (-static_cast<int>(whole));
00170                 }
00171                 else return (Fraction::operator [] (subscript - 1));
00172         }
00173 
00174         //calling object is made equal to object on the right of operator
00175         MFraction& MFraction::operator = (const MFraction &right)
00176         {
00177                 Fraction::operator = (right);   
00178                 if (this != &right) whole = right.whole;
00179                 return (*this); //so tht x = y = z is possible; (x = y) returns a reference which gets equated to z
00180         }
00181 
00182         //negation operator: returns the negated value of fraction, but doesnt change original
00183         MFraction MFraction::operator - () const
00184         {
00185                 if (sign) return (MFraction(-static_cast<int>(whole),numerator,denominator));
00186                 else return (MFraction(whole,numerator,denominator));
00187         }
00188 
00189         //prefix increment operator: adds 1 to fraction
00190         MFraction MFraction::operator ++ ()
00191         {
00192                 return (MFraction::operator ++ (1));
00193         }
00194 
00195         //prefix decrement operator: subtracts 1 from fraction
00196         MFraction MFraction::operator -- ()
00197         {
00198                 return (MFraction::operator -- (1));
00199         }
00200 
00201         //postfix increment operator: increments fraction by inc; if inc is 0, increments by 1
00202         MFraction MFraction::operator ++ (int inc)
00203         {
00204                 if (inc < 0) throw (FR_NEG_PARAM);
00205 
00206                 if (inc == 0) inc = 1;
00207 
00208                 if (sign) whole += inc;
00209                 else if (whole > inc) whole-= inc;
00210                 else
00211                 {
00212                         sign = !sign;
00213                         whole = inc - whole;
00214                 }
00215                 
00216                 return (*this);
00217         }
00218 
00219         //postfix decrement operator: decrements fraction by dec; if dec is 0, decrements by 1
00220         MFraction MFraction::operator -- (int dec)
00221         {
00222                 if (dec < 0) throw (FR_NEG_PARAM);
00223 
00224                 if (dec == 0) dec = 1;
00225 
00226                 if (!sign) whole += dec;
00227                 else if (whole >= dec) whole -= dec;
00228                 else
00229                 {
00230                         sign = !sign;
00231                         whole = dec - whole;
00232                 }
00233 
00234                 return (*this);
00235         }
00236 
00237         //defines the addition/assignment operator
00238         //adds fraction to the right of the operator to Fraction object on the left and returns this object
00239         MFraction MFraction::operator += (const MFraction &right)
00240         {
00241                 *this = *this + right;
00242                 return (*this);
00243         }
00244 
00245         //defines the subtraction/assignment operator
00246         //subtracts fraction to the right of the operator to Fraction object on the left and returns this object
00247         MFraction MFraction::operator -= (const MFraction &right)
00248         {
00249                 *this = *this - right;
00250                 return (*this);
00251         }
00252 
00253         //defines the multiplication/assignment operator
00254         //calling object is multiplied by fraction on the right of the operator and the result is assigned to the calling object
00255         MFraction MFraction::operator *= (const MFraction &right)
00256         {
00257                 *this = *this * right;
00258                 return (*this);
00259         }
00260 
00261         //defines the division/assignment operator
00262         //calling object is divided by fraction on the right of the operator and the result is assigned to the calling object
00263         MFraction MFraction::operator /= (const MFraction &right)
00264         {
00265                 *this = *this / right;
00266                 return (*this);
00267         }
00268 
00269         /************************ FRIENDS OVERLOADED OPERATORS *************************/
00270 
00271         //returns true if 2 fractions are the same
00272         bool operator == (const MFraction &left, const MFraction &right)
00273         {
00274                 return (left.whole==right.whole && left.sign==right.sign && left.numerator==right.numerator && left.denominator==right.denominator);
00275         }
00276 
00277         //returns true if 2 fractions are not the same
00278         bool operator != (const MFraction &left, const MFraction &right)
00279         {
00280                 return (left.whole!=right.whole || left.sign!=right.sign || left.numerator!=right.numerator || left.denominator!=right.denominator);
00281         }
00282 
00283         //returns true if left fraction is less than the fraction on the right of the operator
00284         bool operator < (const MFraction &left, const MFraction &right)
00285         {
00286                 int left_numerator = (left[0]*left.denominator + left[1]) * right.denominator;
00287                 int right_numerator = (right[0]*right.denominator + right[1]) * left.denominator;
00288                 return (left_numerator < right_numerator);      
00289         }
00290 
00291         //returns true if left fraction is less than or equal to the fraction on the right of the operator
00292         bool operator <= (const MFraction &left, const MFraction &right)
00293         {
00294                 return (left<right || left==right);
00295         }
00296 
00297         //returns true if left fraction is greater than the fraction on the right of the operator
00298         bool operator > (const MFraction &left, const MFraction &right)
00299         {
00300                 return (!(left <= right));
00301         }
00302 
00303         //returns true if left fraction is greater than or euqal to the fraction on the right of the operator
00304         bool operator >= (const MFraction &left, const MFraction &right)
00305         {
00306                 return (!(left < right));
00307         }
00308 
00309         //adds 2 fractions on either side of the operator and returns the result
00310         MFraction operator + (const MFraction &left, const MFraction &right)
00311         {
00312                 return (MFraction(0, (left[0]*left.denominator+left[1])*right.denominator+(right[0]*right.denominator+right[1])*left.denominator, left.denominator*right.denominator));
00313         }
00314 
00315         //subtracts 2 fractions on either side of the operator and returns the result
00316         MFraction operator - (const MFraction &left, const MFraction &right)
00317         {
00318                 return (MFraction(0, (left[0]*left.denominator+left[1])*right.denominator-(right[0]*right.denominator+right[1])*left.denominator, left.denominator*right.denominator));
00319         }
00320 
00321         //multiplies 2 fractions on either side of the operator and returns the result
00322         MFraction operator * (const MFraction &left, const MFraction &right)
00323         {
00324                 return (MFraction(0, (left[0]*left.denominator+left[1])*(right[0]*right.denominator+right[1]), left.denominator*right.denominator));
00325         }
00326 
00327         //divides 2 fractions on either side of the operator and returns the result
00328         MFraction operator / (const MFraction &left, const MFraction &right)
00329         {
00330                 return (MFraction(0, (left[0]*left.denominator+left[1])*right.denominator, left.denominator*(right[0]*right.denominator+right[1])));
00331         }
00332 
00333         /**************************** STREAM INPUT/OUTPUT ******************************/
00334 
00335         //stream output
00336         ostream &operator << (ostream &out, const MFraction &fraction)
00337         {
00338                 if (!fraction.sign) out << "-";
00339 
00340                 if (MFraction::FORMAT == MFraction::DECI)
00341                         out << fraction.whole + static_cast<double>(fraction.numerator)/static_cast<double>(fraction.denominator);
00342                 else
00343                 {
00344                         if (MFraction::FORMAT==MFraction::MIX_FRAC)
00345                         {
00346                                 if (fraction.whole != 0) out << fraction.whole;
00347                                 if (fraction.whole != 0 && fraction.numerator != 0) out << "/";  //dont get 5/0 or /0
00348                                 if (!(fraction.whole != 0 && fraction.numerator == 0)) out << fraction.numerator;
00349                         }
00350                         else out << (fraction.whole * fraction.denominator) + fraction.numerator; //if type is of IM_FRAC
00351                         if (fraction.denominator != 1) out << "/" << fraction.denominator;
00352                 }
00353 
00354                 return (out);
00355         }
00356 
00357         //stream input
00358         istream &operator >> (istream &in, MFraction &fraction)
00359         {
00360                 string input;
00361                 in >> input;
00362                 fraction = input.c_str();
00363 
00364                 return (in);
00365         }
00366 #endif