17

### Rational

1. #include <iostream>
2. #include <cstdlib>
3.
4. using namespace std;
5.
6. #ifdef DEBUG
7. int debug = 0;  // 0 - off, 1 - on
8. #endif
9.
10. #ifdef DEBUG
11. #define ONDEBUG( expr ) do { if ( debug ) { expr; } } while ( 0 )
12. #else
13. #define ONDEBUG( expr )
14. #endif
15.
16. class Rational {
17.     friend Rational operator*( const Rational &, const Rational & );
18.     friend bool operator==( const Rational &, const Rational & );
19.     friend ostream &operator<<( ostream &ostr, const Rational &r );
20.     friend istream &operator>>( istream &istr, Rational &r );
21. public:
22.     ~Rational( )
23.     {
24.         cout << "DESTRUCTOR\n";
25.     }
26.     Rational( int n=0, int d=1 ) : num( n ), den( d )
27.     {
28.         cout << "CONSTRUCTOR\n";
29.         reduce();
30.     };
31.     Rational( const Rational &r ) : num( r.num ), den( r.den )
32.     {
33.         cout << "COPY\n";
34.     };
35.     Rational &operator=( const Rational &r )
36.     {
37.         cout << "OPERATOR =\n";
38.         num = r.num;
39.         den = r.den;
40.
41.         return *this;
42.     };
43.     Rational &operator*=( const Rational &r )
44.     {
45.         cout << "OPERATOR *=\n";
46.         num *= r.num;
47.         den *= r.den;
48.
49.         reduce();
50.
51.         return *this;
52.     };
53.     operator double() const;
54.     Rational operator++();
55.     Rational operator++( int );
56.     int &operator[]( int );
57.
58.     void print( ) const { cout << num << '/' << den; }
59.     void printf( ) const { cout << double(num) / double(den); }
60.     int numerator( ) const { return num; }
61.     int denominator( ) const { return den; }
62.
63. private:
64.     int num, den;
65.     int gdc( int x, int y )
66.     {
67.         ONDEBUG( cout << "gdc( " << x << ", " << y << " )" << endl; );
68.         return y == 0 ? x : gdc( y, x%y );
69.     }
70.     void reduce( )
71.     {
72.         int g = gdc( num, den );
73.         ONDEBUG( cout << "gdc=" << g << endl; );
74.         num /= g, den /= g;
75.     }
76. };
77.
78. Rational::operator double() const
79. {
80.     return double(num) / double(den);
81. }
82.
83. Rational Rational::operator++()
84. {
85.     num += den;
86.
87.     return *this;
88. }
89.
90. Rational Rational::operator++( int fake )
91. {
92.     Rational t = *this;
93.     num += den;
94.
95.     return t;
96. }
97.
98. int &Rational::operator[]( int i )
99. {
100.     if ( i == 1 )
101.         return num;
102.     if ( i == 2 )
103.         return den;
104.     cerr << "ERROR: Rational::operator[] - Bad argument";
105.     exit( 1 );
106. }
107.
108. Rational operator*( const Rational &x, const Rational &y )
109. {
110.     cout << "OPERATOR *\n";
111.     Rational z( x.num * y.num, x.den * y.den );
112.     return z;
113. }
114.
115. bool operator==( const Rational &x, const Rational &y )
116. {
117.     cout << "OPERATOR ==\n";
118.
119.     return x.num * y.den == x.den * y.num;
120. }
121.
122. ostream &operator<<( ostream &ostr, const Rational &r )
123. {
124.     ostr << r.num << "/" << r.den;
125.
126.     return ostr;
127. }
128.
129. istream &operator>>( istream &istr, Rational &r )
130. {
131.     cout << "Num? ";
132.     cin >> r.num;
133.     cout << "Den? ";
134.     cin >> r.den;
135.
136.     r.reduce();
137.
138.     return istr;
139. }
140.
141. Rational f( Rational r )
142. {
143.     Rational s = r;
144.
145.     return s;
146. }
147.
148. int main()
149. {
150.     Rational x( 21, 66 );   // will be reduced
151.     Rational y = x;
152.     {
153.         Rational x = 4;
154.         cout << "x=", x.print(), cout << "=", x.printf(), cout << endl;
155.     }
156.     cout << "x=", x.print(), cout << "=", x.printf(), cout << endl;
157.     cout << "y=", y.print(), cout << "=", y.printf(), cout << endl;
158.     cout << endl;
159.
160.     cout << "num=" << x.numerator() << endl;
161.     cout << "den=" << x.denominator() << endl;
162.     cout << endl;
163.     {
164.         const Rational PI( 22, 7 );
165.         cout << "PI=", PI.print(), cout << "=", PI.printf(), cout << endl;
166.         x = PI;
167.     }
168.     cout << "x=", x.print(), cout << "=", x.printf(), cout << endl;
169.     cout << endl;
170.
171.     x = f( y );
172.     cout << endl;
173.     {
174.         Rational x(22, 7);
175.         Rational y(-3, 8);
176.         Rational z = x * y; // calls operator =
177.
178.         cout << "x=", x.print(), cout << endl;
179.         cout << "y=", y.print(), cout << endl;
180.         cout << "z=", z.print(), cout << endl;
181.         cout << endl;
182.
183.         x *= y;
184.         cout << "x=" << x << endl;                          // calls operator <<
185.         cout << (x == z ? "x=y\n" : "x!=y\n");  // calls operator ==
186.     }
187.     cout << endl;
188.     cin >> x;                                                               // calls operator >>
189.     cout << "x=" << x << endl;
190.     cout << "x=" << (double)x << endl;          // calls operator double()
191.     cout << "x=" << (double)++x << endl;        // calls operator ++
192.     cout << "x=" << (double)x++ << endl;        // calls operator ++
193.     cout << "x=" << x << endl;
194.     cout << endl;
195.     x[ 1 ] = 22;                                                        // calls operator []
196.     x[ 2 ] = 7;                                                         // calls operator []
197.     cout << "x=" << (double)x << endl;
198. }