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