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

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