Fraction Library
A C++ Fraction library.

Fraction.cpp

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