home *** CD-ROM | disk | FTP | other *** search
/ Microsoftware Monthly 19…2 Programming Power Tools / MASO9512.ISO / cpptutor / cpptutor.arj / EXAMPLES / EX0920.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1993-10-20  |  6.7 KB  |  199 lines

  1. // \EXAMPLES\EX0920.CPP
  2. //  friends and noninline member functions of Fraction class
  3. //---------------------------------------------------------
  4.  
  5. //  this file is used in the following example programs:
  6. //--------------------------------------------------------------
  7. // %F,15,EX0923.CPP%EX0923.CPP    overloading unary + -
  8. // %F,15,EX0924.CPP%EX0924.CPP    overloading binary operators
  9. // %F,15,EX0925.CPP%EX0925.CPP    overloading =
  10. // %F,15,EX0926.CPP%EX0926.CPP    overloading prefix ++ --
  11. // %F,15,EX0927.CPP%EX0927.CPP    overloading postfix ++ --
  12. //---------------------------------------------------------------
  13. // This file must be used with
  14. // %F,15,EX0920.H%EX0920.H      definition of Fraction class
  15. //---------------------------------------------------------------
  16.  
  17. #ifndef FRAC_CPP
  18. #define FRAC_CPP
  19.  
  20. #include <iostream.h>
  21. #include <strstrea.h>        // #include <strstream.h>
  22. #include <limits.h>
  23. #include "EX0920.H"
  24.  
  25. //---------------------------------------------------------
  26. // Constructor - conversion from float or double
  27. //---------------------------------------------------------
  28.  
  29. Fraction::Fraction(double x) : num(0), denom(1)
  30. {
  31.   double y = x < 0 ? -x : x;     // ignore sign if < 0
  32.   int n = int(y);                // set num = whole part
  33.   int d = 1;                     // set denom = 1
  34.   y -= n;                        // set y to fractional part
  35.   int acc = INT_MAX >> 1;        // for largest num & denom
  36.   float dacc = 1.0/INT_MAX;      // to prevent infinite loop
  37.   while ( n < acc && d < acc )   // stop before overflow
  38.   {                              // parse y bit by bit
  39.     n <<= 1; d <<=1;             // left shift num & denom
  40.     y += y;                      // next bit of accuracy in y
  41.     if (y >= 1.0) { n +=1; y -=1; }     // ? update num & denom
  42.     if ( y < dacc ) break;       // stop if residue very small
  43.   };
  44.   if ( x < 0 ) n = -n;           // reinstate sign if < 0
  45.   num = n; denom = d; reduce();  // create the Fraction
  46. }
  47.  
  48. //---------------------------------------------------------
  49. // private member function reduce --> to simlest form
  50. //        --> minus sign in numerator only
  51. //        --> divide by common factors  -- gcd(num,denom)
  52. //---------------------------------------------------------
  53. void
  54. Fraction::reduce()
  55. {
  56.   if ( denom == 0 )                     // if demoninator 0
  57.   {  num = 0; denom = 1; }                 //  set to 0/1
  58.   if ( denom < 0 )                      // if demoninator
  59.   { num = - num; denom = - denom; }        //  move sign to num
  60.   int g = gcd(num, denom);              // find greatest common
  61.   if (g > 1)                               //  denominator
  62.   { num = num/g; denom = denom/g;}      // simplify fraction
  63. }
  64. //---------------------------------------------------------
  65. // Euclid's algorithm for greatest common demoninator
  66. //     the principle: gcd(x,0) = x
  67. //                    gcd(x,y) = gcd(y,x%y)
  68. //          examples: gcd(336,15) = gcd(15,6)
  69. //                                = gcd(6,3)
  70. //                                = gcd(3,0)
  71. //                                = 3
  72. //                       gcd(3,2) = gcd(2,1)
  73. //                                = gcd(1,0)
  74. //                                = 1
  75. //---------------------------------------------------------
  76. // private member function greated common divisor
  77. //---------------------------------------------------------
  78. int
  79. Fraction::gcd(int n, int d)
  80. {
  81.   n = n < 0 ? -n : n;                      // use absolute value
  82.   return n % d == 0 ? d : gcd( d, n % d);  // recursive call gcd
  83. }
  84.  
  85. //---------------------------------------------------------
  86. // overload << operator  -->  ostream << Fraction
  87. //---------------------------------------------------------
  88. ostream&
  89. operator<<( ostream& os, const Fraction& F )
  90. {
  91.    os << F.num << "/" << F.denom;
  92.    return os;
  93. }
  94.  
  95. //---------------------------------------------------------
  96. // overload >> operator  -->  istream >> Fraction
  97. //---------------------------------------------------------
  98. istream&
  99. operator>>( istream& is, Fraction& F)
  100. {
  101.    char c;                            // to hold the '/'
  102.    F.num = 0;                         // default numerator
  103.    F.denom = 1;                       // default denominator
  104.    char buffer[20];                   // for reformatting
  105.    ostrstream oss(buffer,26,ios::out);   // in-memory output
  106.    istrstream iss(buffer,26);            // in-memory input
  107.    char token[20];                    // to hold raw input
  108.    is >> token;                       // read as  string
  109.    oss << token << "/1" << ends;      // write to memory
  110.    iss >> F.num >> c >> F.denom;      // read int-char-int
  111.    if ( c != '/' ) F.denom = 1;       // check syntax n/d
  112.    F.reduce();                        // simplify fraction
  113.    return is;
  114. }
  115. //---------------------------------------------------------
  116.  
  117. //---------------------------------------------------------
  118. // binary arithmetic operators
  119. //---------------------------------------------------------
  120.  
  121. Fraction operator+(const Fraction& f1, const Fraction& f2)
  122. {
  123.   int n = (f1.num * f2.denom) + (f2.num * f1.denom);
  124.   int d = f1.denom * f2.denom;
  125.   return Fraction(n,d);
  126. }
  127.  
  128. Fraction operator-(const Fraction& f1, const Fraction& f2)
  129. {
  130.   int n = (f1.num * f2.denom) - (f2.num * f1.denom);
  131.   int d = (f1.denom * f2.denom);
  132.   return Fraction(n,d);
  133. }
  134.  
  135. Fraction operator*(const Fraction& f1, const Fraction& f2)
  136. {
  137.   int n = (f1.num * f2.num);
  138.   int d = (f1.denom * f2.denom);
  139.   return Fraction(n,d);
  140. }
  141.  
  142. Fraction operator/(const Fraction& f1, const Fraction& f2)
  143. {
  144.   int n = (f1.num * f2.denom);
  145.   int d = (f1.denom * f2.num);
  146.   return Fraction(n,d);
  147. }
  148.  
  149. //---------------------------------------------------------
  150. // unary arithmetic operators
  151. //---------------------------------------------------------
  152.  
  153. Fraction operator+(const Fraction& f)
  154. {
  155.   return f;
  156. }
  157.  
  158. Fraction operator-(const Fraction& f)
  159. {
  160.   return Fraction(-f.num,f.denom);
  161. }
  162.  
  163. //---------------------------------------------------------
  164. // Increment and Decrement operators prefix ++ --
  165. //---------------------------------------------------------
  166.  
  167. Fraction operator++ (Fraction& f)
  168. {
  169.    f.num += f.denom;
  170.    return f;
  171. }
  172.  
  173.  
  174. Fraction operator-- (Fraction& f)
  175. {
  176.    f.num -= f.denom;
  177.    return f;
  178. }
  179. //---------------------------------------------------------
  180. // Increment and Decrement operators postfix ++ --
  181. //---------------------------------------------------------
  182.  
  183. Fraction operator++ (Fraction& f, int)
  184. {
  185.    Fraction oldFrac = f;
  186.    f.num += f.denom;
  187.    return oldFrac;
  188. }
  189.  
  190.  
  191. Fraction operator-- (Fraction& f, int)
  192. {
  193.    Fraction oldFrac = f;
  194.    f.num -= f.denom;
  195.    return oldFrac;
  196. }
  197.  
  198. #endif
  199.