home *** CD-ROM | disk | FTP | other *** search
- // \EXAMPLES\EX10021.CPP
- // member and friend functions of the Fraction class
- //---------------------------------------------------------
-
- // files in this example:
- // %F,15,EX10021.H%EX10021.H definition of the class Fraction
- // EX10021.CPP this file
- // %F,15,EX1002.CPP%EX1002.CPP main() to exercise Fraction class
- //---------------------------------------------------------
-
- #ifndef FRAC_CPP
- #define FRAC_CPP
-
- #include <iostream.h>
- #include <strstrea.h> // #include <strstream.h>
- #include <limits.h>
- #include "EX10021.H"
-
- //---------------------------------------------------------
- // Functions used in implementation of Fraction
- //---------------------------------------------------------
-
- //---------------------------------------------------------
- // Constructor - conversion from float or double
- //---------------------------------------------------------
-
- Fraction::Fraction(double x) : num(0), denom(1)
- {
- double y = x < 0 ? -x : x; // ignore sign if < 0
- int n = int(y); // set num = whole part
- int d = 1; // set denom = 1
- y -= n; // set y to fractional part
- int acc = INT_MAX >> 1; // for largest num & denom
- float dacc = 1.0/INT_MAX; // to prevent infinite loop
- while ( n < acc && d < acc ) // stop before overflow
- { // parse y bit by bit
- n <<= 1; d <<=1; // left shift num & denom
- y += y; // next bit of accuracy in y
- if (y >= 1.0) { n +=1; y -=1; } // ? update num & denom
- if ( y < dacc ) break; // stop if residue very small
- };
- if ( x < 0 ) n = -n; // reinstate sign if < 0
- num = n; denom = d; reduce(); // create the Fraction
- }
-
- //---------------------------------------------------------
- // private member function reduce --> to simlest form
- // --> minus sign in numerator only
- // --> divide by common factors -- gcd(num,denom)
- //---------------------------------------------------------
- void
- Fraction::reduce()
- {
- if ( denom == 0 ) // if demoninator 0
- { num = 0; denom = 1; } // set to 0/1
- if ( denom < 0 ) // if demoninator
- { num = - num; denom = - denom; } // move sign to num
- int g = gcd(num, denom); // find greatest common
- if (g > 1) // divisor
- { num = num/g; denom = denom/g;} // simplify fraction
- }
- //---------------------------------------------------------
- // Euclid's algorithm for greatest common demoninator
- // the principle: gcd(x,0) = x
- // gcd(x,y) = gcd(y,x%y)
- // examples: gcd(336,15) = gcd(15,6)
- // = gcd(6,3)
- // = gcd(3,0)
- // = 3
- // gcd(3,2) = gcd(2,1)
- // = gcd(1,0)
- // = 1
- //---------------------------------------------------------
- // private member function greated common divisor
- //---------------------------------------------------------
- int
- Fraction::gcd(int n, int d)
- {
- n = n < 0 ? -n : n; // use absolute value
- return n % d == 0 ? d : gcd( d, n % d); // recursive call gcd
- }
- //---------------------------------------------------------
- // member function display display()
- // print whole part separately if > 1 in format i_n/d
- //---------------------------------------------------------
- ostream&
- Fraction::display(ostream& os)
- {
- int nn = num;
- if ( nn < 0 )
- { nn = -nn; os << "-";}
- if (nn < denom)
- os << nn << "/" << denom;
- else
- {
- os << nn/denom;
- if (nn % denom > 0)
- os << "_" << nn % denom << "/" << denom;
- }
- return os;
- }
-
- //---------------------------------------------------------
- // friend function print()
- // print the fraction as an improper fraction
- //---------------------------------------------------------
- ostream&
- print(const Fraction& F, ostream& os)
- {
- os << F.num << "/" << F.denom;
- return os;
- }
-
- //---------------------------------------------------------
- // overload << operator --> ostream << Fraction
- //---------------------------------------------------------
- ostream&
- operator<<( ostream& os, const Fraction F )
- {
- os << F.num << "/" << F.denom;
- return os;
- }
-
- //---------------------------------------------------------
- // overload >> operator --> istream >> Fraction
- //---------------------------------------------------------
- istream&
- operator>>( istream& is, Fraction& F)
- {
- char c; // to hold the '/'
- F.num = 0; // default numerator
- F.denom = 1; // default denominator
- char buffer[20]; // for reformatting
- ostrstream oss(buffer,26,ios::out); // in-memory output
- istrstream iss(buffer,26); // in-memory input
- char token[20]; // to hold raw input
- is >> token; // read as string
- oss << token << "/1" << ends; // write to memory
- iss >> F.num >> c >> F.denom; // read int-char-int
- if ( c != '/' ) F.denom = 1; // check syntax n/d
- F.reduce(); // simplify fraction
- return is;
- }
-
- //---------------------------------------------------------
- // member function invert
- // invert a fraction, keep sign in numerator
- //---------------------------------------------------------
- Fraction
- Fraction::invert()
- {
- if ( num == 0 )
- return *this; // do not invert 0/1
- int temp = num < 0 ? -num : num;
- num = num < 0 ? -denom : denom;
- denom = temp;
- return *this;
- }
-
- //---------------------------------------------------------
- // friend function double
- // type conversion to floating point
- //---------------------------------------------------------
-
- double
- real(const Fraction& F)
- {
- return double(F.num)/double(F.denom);
- }
-
- //---------------------------------------------------------
- // friend function int
- // type conversion to integer
- //---------------------------------------------------------
- int
- trunc(const Fraction& F)
- {
- return F.num / F.denom;
- }
-
- //------------------------------------------------------
- // overload operators = - * / binary arithmetic
- //------------------------------------------------------
-
- Fraction
- operator+( const Fraction& f1, const Fraction& f2)
- {
- int n = f1.num * f2.denom + f2.num * f1.denom;
- int d = f1.denom * f2.denom;
- return Fraction(n,d);
- }
-
- Fraction
- operator-( const Fraction& f1, const Fraction& f2)
- {
- int n = f1.num * f2.denom - f2.num * f1.denom;
- int d = f1.denom * f2.denom;
- return Fraction(n,d);
- }
-
- Fraction
- operator*( const Fraction& f1, const Fraction& f2)
- {
- int n = f1.num * f2.num;
- int d = f1.denom * f2.denom;
- return Fraction(n,d);
- }
-
- Fraction
- operator/( const Fraction& f1, const Fraction& f2)
- {
- int n = f1.num * f2.denom;
- int d = f1.denom * f2.num;
- return Fraction(n,d);
- }
-
- //---------------------------------------------------------
-
- #endif
-