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

  1. // \EXAMPLES\EX1301.CPP
  2.  
  3. // cout and cin from iostream
  4. #include <iostream.h>
  5. // MAX_INT used to prevent integer overflow in fraction
  6. #include <limits.h>
  7.  
  8. // this global function is called by member function reduce()
  9. int gcd(int n,int d);
  10.  
  11. //
  12. // Fraction base class
  13. //
  14. class fraction {
  15. protected:            // the derived classes need access to these
  16.    int num;           // num includes the sign of fraction
  17.    int denom;         // denominator always positive
  18.    virtual void reduce ()=0;    // put Fractions in simplest form
  19. public:
  20.    fraction (int i=0, int j=1): num(i), denom(j) { };
  21.    fraction (double);
  22.    ~fraction() {};
  23.    friend istream& operator>>(istream& i, fraction& f);
  24. };
  25.  
  26. //
  27. // pfraction class
  28. // derived from fraction
  29. //
  30.  
  31. class pfraction : public fraction {
  32. public:
  33.    // constructors
  34.    pfraction (int i=0, int j=1): fraction(i,j) { reduce(); };
  35.    pfraction (double x);
  36.    // conversion functions
  37.    operator double();
  38.    operator int();
  39.    void reduce();
  40.    // prefix increment and decrement
  41.    pfraction operator++ ()
  42.    { return pfraction ( num + denom, denom); };
  43.    pfraction operator-- ()
  44.    { return pfraction ( num - denom, denom); };
  45.    // postfix increment and decrement
  46.    pfraction operator++ (int)
  47.    { return pfraction( num + denom, denom); };
  48.    pfraction operator-- (int)
  49.    { return pfraction( num - denom, denom); };
  50.    // overloading > == and <
  51.    friend
  52.    int operator>(const pfraction& f1, const pfraction& f2);
  53.    friend
  54.    int operator==(const pfraction& f1, const pfraction& f2);
  55.    friend
  56.    int operator<(const pfraction& f1, const pfraction& f2);
  57.    // overloading unary math operators + - ++ -- ...
  58.    pfraction operator+ ();
  59.    pfraction operator- ();
  60.    // overloading binary math operators  +  -  *  /   ...
  61.    friend
  62.    pfraction operator+(const pfraction& f1, const pfraction& f2);
  63.    friend
  64.    pfraction operator-(const pfraction& f1, const pfraction& f2);
  65.    friend
  66.    pfraction operator*(const pfraction& f1, const pfraction& f2);
  67.    friend
  68.    pfraction operator/(const pfraction& f1, const pfraction& f2);
  69.    // output operator
  70.    friend
  71.    ostream& operator<<(ostream& , const pfraction&);
  72. };
  73.  
  74. //
  75. // mfraction class
  76. // derived from fraction
  77. //
  78. //
  79. // In this class, the whole part of the fraction is stored
  80. // separately from the fractional part.  If the value can be
  81. // expressed as a proper fraction, the whole part equals zero.
  82. //
  83.  
  84. class mfraction : public fraction {
  85. private:
  86.    int whole;
  87. public:
  88.    // constructors
  89.    mfraction (int i=0, int j=0, int k = 1) :
  90.       whole(i), fraction(j,k)
  91.       { reduce(); }
  92.    mfraction (double x);
  93.    // conversion functions
  94.    operator double();
  95.    operator int();
  96.    void make_pure();
  97.    void reduce();
  98.    // prefix forms
  99.    mfraction operator++ ()
  100.    { return mfraction ( whole++, num, denom); };
  101.    mfraction operator-- ()
  102.    { return mfraction ( whole--, num, denom); };
  103.    // postfix forms
  104.    mfraction operator++ (int)
  105.    { return mfraction( whole++, num, denom); };
  106.    mfraction operator-- (int)
  107.    { return mfraction( whole--, num, denom); };
  108.    // overloading > == and <
  109.    friend
  110.    int operator> (const mfraction& f1, const mfraction& f2);
  111.    friend
  112.    int operator== (const mfraction& f1, const mfraction& f2);
  113.    friend
  114.    int operator< (const mfraction& f1, const mfraction& f2);
  115.    // overloading unary math operators + - ++ -- ...
  116.    mfraction operator+ ();
  117.    mfraction operator- ();
  118.    // overloading binary math operators  +  -  *  /   ...
  119.    friend mfraction
  120.    operator+ (const mfraction& f1, const mfraction& f2);
  121.    friend mfraction
  122.    operator- (const mfraction& f1, const mfraction& f2);
  123.    friend mfraction
  124.    operator* (const mfraction& f1, const mfraction& f2);
  125.    friend mfraction
  126.    operator/ (const mfraction& f1, const mfraction& f2);
  127.    // output operator
  128.    friend ostream& operator<<(ostream& , const mfraction&);
  129. };
  130.  
  131. //
  132. // Conversion functions for pfraction and mfraction
  133. //
  134.  
  135. double pfraction::operator double(pfraction f) {
  136.    return double(num)/double(denom);
  137.    }
  138.  
  139. double mfraction::operator double(mfraction f) {
  140.    return whole + (double(num)/double(denom));
  141.    }
  142.  
  143. int pfraction::operator int(int i) {
  144.    return int(double(num)/double(denom));
  145.    }
  146.  
  147. int mfraction::operator int(int i) {
  148.    return whole + int(double(num)/double(denom));
  149.    }
  150.  
  151. //
  152. // input and output operators for pfraction and mfraction
  153. //
  154.  
  155. ostream& operator<<(ostream& o, const pfraction& f) {
  156.    o << f.num << "/" << f.denom;
  157.    return o;
  158. }
  159.  
  160. ostream& operator<<(ostream& o, const mfraction& f) {
  161.    o << f.whole << " " << f.num << "/" << f.denom;
  162.    return o;
  163. }
  164.  
  165. istream& operator>>(istream& i, fraction& f) {
  166.    char c;
  167.    i >> f.num >> c >> f.denom;
  168.    f.reduce();
  169.    return i;
  170. }
  171.  
  172. //
  173. // Definitions:
  174. //    arithmetic operators for pfraction and mfraction.
  175.  
  176. pfraction operator+ (const pfraction& f1, const pfraction& f2 ) {
  177.   int n = f1.num*f2.denom + f2.num*f1.denom;
  178.   int d = f1.denom * f2.denom;
  179.   return pfraction(n,d);
  180. }
  181.  
  182. mfraction operator+ (const mfraction& f1, const mfraction& f2 ) {
  183.   int n = f1.num*f2.denom + f2.num*f1.denom;
  184.   int d = f1.denom * f2.denom;
  185.   int w = f1.whole + f2.whole;
  186.   if ( w*n < 0 ) {    // do signs of whole and fraction agree
  187.      if ( n < 0 ) {   // if fraction negative, subtract one from
  188.         n = n + d;    // whole and add to fraction
  189.         w--;
  190.      }
  191.      else  {
  192.         n = n - d;    // if fraction positive, subtract one from
  193.         w++;          // fraction and add to whole
  194.      }
  195.   }
  196.   return mfraction(w,n,d);
  197. }
  198.  
  199. pfraction operator- ( const pfraction& f1, const pfraction& f2 )
  200. {
  201.   int n = f1.num*f2.denom - f2.num*f1.denom;
  202.   int d = f1.denom * f2.denom;
  203.   return pfraction(n,d);
  204. }
  205.  
  206. mfraction operator- ( const mfraction& f1, const mfraction& f2 )
  207. {
  208.    int n = f1.num*f2.denom - f2.num*f1.denom;
  209.    int d = f1.denom * f2.denom;
  210.    int w = f1.whole - f2.whole;
  211.    if ( w*n < 0 ) {    // do signs of whole and fraction agree
  212.       if ( n < 0 ) {   // if fraction negative, subtract one from
  213.         n = n + d;     // whole and add to fraction
  214.         w--;
  215.      }
  216.      else  {
  217.         n = n - d;     // if fraction positive, subtract one from
  218.         w++;           // fraction and add to whole
  219.      }
  220.   }
  221.   return mfraction(w,n,d);
  222. }
  223.  
  224. pfraction operator* ( const pfraction& f1, const pfraction& f2 )
  225. {
  226.   int n = f1.num * f2.num;
  227.   int d = f1.denom * f2.denom;
  228.   return pfraction(n,d);
  229. }
  230.  
  231. mfraction operator* ( const mfraction& f1, const mfraction& f2 )
  232. {
  233.    int n = f1.num * f2.num;
  234.    int d = f1.denom * f2.denom;
  235.    int n2 = f1.num * f2.whole * f2.denom;
  236.    int n3 = f2.num * f1.whole * f1.denom;
  237.    int w = f1.whole * f2.whole;
  238.    if ( w*n < 0 ) {    // do signs of whole and fraction agree
  239.      if ( n < 0 ) {    // if fraction negative, subtract one from
  240.         n = n + d;     // whole and add to fraction
  241.         w--;
  242.      }
  243.      else  {
  244.         n = n - d;     // if fraction positive, subtract one from
  245.         w++;           // fraction and add to whole
  246.      }
  247.   }
  248.   return mfraction(w,n + n2 + n3,d);
  249. }
  250.  
  251. pfraction operator/( const pfraction& f1, const pfraction& f2 )
  252. {
  253.   int n = f1.num * f2.denom;
  254.   int d = f1.denom * f2.num;
  255.   return pfraction(n,d);
  256. }
  257.  
  258. mfraction operator/( const mfraction& f1, const mfraction& f2 )
  259. {
  260.    mfraction ft1 = f1;
  261.    mfraction ft2 = f2;
  262.    ft1.make_pure();         // convert to pure fractions
  263.    ft2.make_pure();
  264.    int n = ft1.num * ft2.denom;
  265.    int d = ft1.denom * ft2.num;
  266.    return mfraction(0,n,d);
  267. }
  268.  
  269. //
  270. // Functions used in implementation of fraction
  271. //
  272.  
  273. fraction::fraction(double x) : num(0), denom(1)
  274. {
  275.    double y = x < 0 ? -x : x;        // avoid negative numbers
  276.    int n = int(y);                   // numerator = whole part
  277.    int d = 1;                        // denominator
  278.    y -= n;                           // y is fractional
  279.    int acc = INT_MAX >> 1 ;          // accuracy is limited
  280.    while ( n < acc && d < acc ) {    // stop before overflow
  281.       n <<= 1; d <<=1;               // parse bit by bit
  282.       y += y;                        // next bit of accuracy
  283.       if (y >= 1.0) { n +=1; y -=1; }//
  284.       if ( y < 1e-10 ) break;        // stop when residue tiny
  285.    };
  286.    if ( x < 0 ) n = -n;             // reinstate sign if < 0
  287.    num = n; denom = d; reduce();    // create the fraction
  288. }
  289.  
  290. //
  291. // reduce for pfraction
  292. //
  293. // This function reduces a pfraction object to its simplest form.
  294. //
  295.  
  296.  
  297. void pfraction::reduce()
  298. {
  299.    // what to do when demon = 0? for simplicity set fraction=0/1
  300.    if ( denom == 0 ) {  num = 0; denom = 1; }
  301.    // check sign - should be on num only
  302.    if ( denom < 0 ) { num = - num; denom = - denom; };
  303.    // reduce to simplest form
  304.    // - divide num and demon by greatest common factor
  305.    int g = gcd(num, denom);
  306.    if (g > 1) { num = num/g; denom = denom/g;};
  307. };
  308.  
  309. //
  310. // reduce for mfraction
  311. //
  312. // Reduces mfraction object to simplest form.  Ensures that sign
  313. // of whole part and fractional part agree.  Ensures that
  314. // fractional part is a proper fraction.
  315. //
  316.  
  317. void mfraction::reduce()
  318. {
  319.    // what to do when demon = 0? for simplicity set fraction=0/1
  320.    if ( denom == 0 ) {  num = 0; denom = 1; }
  321.    // check sign - should be on num only
  322.    if ( denom < 0 ) { num = - num; denom = - denom; };
  323.    // reduce to simplest form
  324.    // - divide num and demon by greatest common factor
  325.    int g = gcd(num, denom);
  326.    if (g > 1) { num = num/g; denom = denom/g;}
  327.    // express as a mixed fraction
  328.    whole = whole + int(num/denom);
  329.    num = num%denom;
  330.    // ensure sign is on whole part unless whole part is zero
  331.    if ( num < 0 && whole != 0 ) {
  332.    if ( whole < 0 ) {
  333.          num = - num;
  334.       }
  335.       else {
  336.          num = num + denom;
  337.          whole--;
  338.       }
  339.    }
  340. }
  341.  
  342. //
  343. // make_pure for mfraction
  344. //
  345. // Convert the mixed fraction into a mixed fraction
  346. // where the whole part is equal to zero.
  347. //
  348.  
  349. void mfraction::make_pure() {
  350.    num = num + (denom * whole);
  351.    whole = 0;
  352. }
  353.  
  354. //
  355. // gcd function
  356. //
  357. // Takes two integer arguments.  Returns the
  358. // greatest common divisor of these two values.
  359. //
  360.  
  361. int gcd(int nn, int dd)   // Euclid's algorithm for gcd
  362. { int n = nn < 0 ? -nn : nn;
  363.   int d = dd < 0 ? -dd : dd;
  364.   return n % d == 0 ? d : gcd( d, n % d);
  365. };
  366.  
  367. //
  368. // main() function
  369. //
  370. // Creates two mfraction objects and performs
  371. // arithmetic operations on them.
  372. //
  373.  
  374. void main() {
  375.    mfraction mf1, mf2;
  376.    cout << " Enter two fractions " << endl;
  377.    cin >> mf1 >> mf2;
  378.    cout << " Here is mf1 " << mf1 << endl;
  379.    cout << " Here is mf2 " << mf2 << endl;
  380.    cout << " Sum is: " << mf1 + mf2 << endl;
  381.    cout << " Difference is: " << mf1 - mf2 << endl;
  382.    cout << " Product is: " << mf1 * mf2 << endl;
  383.    cout << " Quotient is: " << mf1 / mf2 << endl;
  384. }
  385.  
  386.