Fraction Library
A C++ Fraction library.
|
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