00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <iostream>
00019 using namespace std;
00020 #ifndef rational_h
00021 #define rational_h
00022
00023
00024
00025
00026
00027
00028
00029 template <class INT>
00030 class rational {
00031 private:
00032 INT m_num;
00033 INT m_den;
00034
00035 void Simplify();
00036
00037 public:
00038
00039 rational() : m_num(0), m_den(1) { }
00040 rational(INT num) : m_num(num), m_den(1) { }
00041 rational(INT num, INT den)
00042 : m_num(num), m_den(den) { Simplify(); }
00043 rational(const rational& o)
00044 { m_num = o.m_num, m_den = o.m_den; }
00045 ~rational() { }
00046
00047 void set(INT num=0, INT den=1);
00048
00049 INT num() const { return m_num; }
00050 INT den() const { return m_den; }
00051
00052
00053
00054
00055 rational& operator = (const rational&);
00056 rational& operator = (INT);
00057 rational& swap ( rational& );
00058
00059 rational& operator += (const rational&);
00060 rational& operator -= (const rational&);
00061 rational& operator *= (const rational&);
00062 rational& operator /= (const rational&);
00063
00064 rational operator - () const;
00065 template <class T>
00066 friend rational<T> operator + (const rational<T>&, const rational<T>&);
00067 template <class T>
00068 friend rational<T> operator - (const rational<T>&, const rational<T>&);
00069 template <class T>
00070 friend rational operator * (const rational<T>&, const rational<T>&);
00071 template <class T>
00072 friend rational<T> operator / (const rational<T>&, const rational<T>&);
00073
00074 template <class T>
00075 friend bool operator == (const rational<T>&, const rational<T>&);
00076 template <class T>
00077 friend bool operator < (const rational<T>&, const rational<T>&);
00078 template <class T>
00079 friend bool operator != (const rational<T>&, const rational<T>&);
00080 template <class T>
00081 friend bool operator <= (const rational<T>&, const rational<T>&);
00082 template <class T>
00083 friend bool operator >= (const rational<T>&, const rational<T>&);
00084 template <class T>
00085 friend bool operator > (const rational<T>&, const rational<T>&);
00086
00087 template <class T>
00088 friend ostream& operator << (ostream &, const rational<T>& );
00089 template <class T>
00090 friend istream& operator >> (istream &, rational<T>& );
00091 rational& fromString (const char* nStr);
00092
00093 template <class T>
00094 friend double real (const rational<T>& );
00095 template <class T>
00096 friend INT integer(const rational<T>& );
00097
00098 template <class T>
00099 friend bool check_ok( const rational<T>& r );
00100
00101
00102
00103 };
00104
00105 template <class INT>
00106 INT mcd(INT x, INT y);
00107
00108
00109 template <class INT>
00110 inline INT gcd(INT x, INT y) { return mcd(x,y); }
00111
00112
00113 template <class INT>
00114 inline void rational<INT>::set(INT n, INT d) {
00115 m_num = n;
00116 m_den = d;
00117 Simplify();
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 template <class INT>
00128 inline rational<INT>& rational<INT>::operator = (const rational& o) {
00129 m_num = o.m_num,
00130 m_den = o.m_den;
00131
00132
00133 return *this;
00134 }
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144 template <class INT>
00145 inline rational<INT>& rational<INT>::swap ( rational<INT>& o ) {
00146 #if 1
00147 rational tmp = o;
00148 o = *this;
00149 *this = tmp;
00150 #else
00151
00152 char tmp[ sizeof( *this ) ];
00153 memcpy( tmp, o, sizeof( *this ) );
00154 memcpy( o, *this, sizeof( *this ) );
00155 memcpy( *this, tmp, sizeof( *this ) );
00156 #endif
00157 return *this;
00158 }
00159
00160
00161 template <class INT>
00162 inline rational<INT>& rational<INT>::operator = (INT entero) {
00163 m_num = entero;
00164 m_den = 1;
00165 return *this;
00166 }
00167
00168
00169 template <class INT>
00170 inline rational<INT>& rational<INT>::operator *= (const rational& num) {
00171 m_num *= num.m_num;
00172 m_den *= num.m_den;
00173 Simplify();
00174 return *this;
00175 }
00176
00177
00178
00179
00180
00181 template <class INT>
00182 inline rational<INT>& rational<INT>::operator /= (const rational& num) {
00183 m_num *= num.m_den;
00184 m_den *= num.m_num;
00185 Simplify();
00186 return *this;
00187 }
00188
00189
00190
00191
00192 template <class INT>
00193 inline rational<INT> rational<INT>::operator - () const {
00194 rational tmp = (*this);
00195 tmp.m_num = - tmp.m_num;
00196 return tmp;
00197 }
00198
00199
00200 template <class INT>
00201 inline bool operator == (const rational<INT> &x, const rational<INT> &y) {
00202 return (x.m_num == y.m_num) && (x.m_den == y.m_den);
00203
00204
00205
00206
00207
00208
00209 }
00210
00211
00212 template <class INT>
00213 inline bool operator < (const rational<INT> &x, const rational<INT> &y) {
00214 return (x.m_num * y.m_den) < (x.m_den * y.m_num);
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 }
00232
00233
00234 template <class INT>
00235 inline bool operator > (const rational<INT> &x, const rational<INT> &y) {
00236 return (y < x);
00237 }
00238
00239
00240 template <class INT>
00241 inline bool operator != (const rational<INT>& x, const rational<INT>& y) {
00242 return !(x == y);
00243 }
00244
00245
00246 template <class INT>
00247 inline bool operator <= (const rational<INT>& x, const rational<INT>& y) {
00248 return !(y < x);
00249 }
00250
00251
00252 template <class INT>
00253 inline bool operator >= (const rational<INT>& x, const rational<INT>& y) {
00254 return !(x < y);
00255 }
00256
00257
00258 template <class INT>
00259 inline double real(const rational<INT>& num) {
00260 return double (num.m_num) / double (num.m_den);
00261 }
00262
00263
00264 template <class INT>
00265 inline INT integer(const rational<INT>& num) {
00266 return INT (num.m_num / num.m_den);
00267 }
00268
00269 #if 0
00270
00271 inline rational<INT>::operator INT() {
00272 return INT (m_num / m_den);
00273 }
00274 #endif
00275
00276 template <class INT>
00277 bool check_ok_externo( const rational<INT>& r );
00278
00279
00280 #include <cstdlib>
00281 #include <cctype>
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299 template <class INT>
00300 bool check_ok( const rational<INT>& r ) {
00301 if (&r == 0) {
00302
00303 return false;
00304 }
00305
00306 if ( ! (r.m_den > 0) ) {
00307
00308 return false;
00309 }
00310 if (r.m_num == 0) {
00311 if ( r.m_den == 1 ) {
00312
00313 return true;
00314 }
00315 else {
00316 return false;
00317 }
00318 }
00319 if ( ! ( mcd(r.m_num, r.m_den) == 1 ) ) {
00320
00321 return false;
00322 }
00323 return true;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335 template <class INT>
00336 bool check_ok_no_Rep( const rational<INT>& r ) {
00337 if (&r == 0) {
00338
00339 return false;
00340 }
00341
00342 if ( ! (r.den() > 0) ) {
00343
00344 return false;
00345 }
00346 if (r.num() == 0) {
00347 if ( r.den() == 1 ) {
00348
00349 return true;
00350 }
00351 else {
00352 return false;
00353 }
00354 }
00355 if ( ! ( mcd(r.num(), r.den()) == 1 ) ) {
00356
00357 return false;
00358 }
00359 return true;
00360 }
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379 template <class INT>
00380 INT mcd(INT x, INT y) {
00381 INT g = (x < 0 ? -x : x);
00382 INT r = (y < 0 ? -y : y);
00383 INT temp;
00384
00385 do {
00386 temp = r;
00387 r = g % r;
00388 g = temp;
00389 } while (0 != r);
00390
00391 return g;
00392 }
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 template <class INT>
00406 void rational<INT>::Simplify() {
00407 if (m_num == 0) {
00408 m_den = 1;
00409 }
00410 INT divisor = mcd(m_num, m_den);
00411 if (divisor > 1) {
00412 m_num /= divisor;
00413 m_den /= divisor;
00414 }
00415 if (m_den < 0) {
00416 m_num = -m_num;
00417 m_den = -m_den;
00418 }
00419 }
00420
00421
00422 template <class INT>
00423 rational<INT>& rational<INT>::operator += (const rational& otro) {
00424 m_num = m_num * otro.m_den + m_den * otro.m_num;
00425 m_den *= otro.m_den;
00426 Simplify();
00427
00428 return *this;
00429 }
00430
00431
00432
00433 template <class INT>
00434 rational<INT>& rational<INT>::operator -= (const rational& otro) {
00435 INT oldm_den = m_den;
00436 INT oldm_num = m_num;
00437 INT d = otro.m_den;
00438 INT n = otro.m_num;
00439
00440 m_den *= d;
00441 m_num = oldm_num * d - oldm_den * n;
00442 Simplify();
00443
00444 return *this;
00445 }
00446
00447
00448
00449 template <class INT>
00450 rational<INT>& rational<INT>::fromString (const char* nStr) {
00451 char ch;
00452
00453 bool es_positivo = true;
00454
00455
00456 do {
00457 ch = *nStr; nStr++;
00458 if (ch == '-') {
00459 es_positivo = !es_positivo;
00460 }
00461 } while (!isdigit(ch));
00462
00463
00464 INT num = 0;
00465 while (isdigit(ch)) {
00466 num = 10 * num + (ch-'0');
00467 ch = *nStr; nStr++;
00468 }
00469
00470
00471 while (isspace(ch)) {
00472 ch = *nStr; nStr++;
00473 }
00474
00475 INT den;
00476 if (ch ==']') {
00477 den = 1;
00478 }
00479 else {
00480 do {
00481 ch = *nStr; nStr++;
00482 if (ch == '-') {
00483 es_positivo = !es_positivo;
00484 }
00485 } while (!isdigit(ch));
00486
00487
00488 den = 0;
00489 while (isdigit(ch)) {
00490 den = 10 * den + (ch-'0');
00491 ch = *nStr; nStr++;
00492 }
00493
00494 }
00495
00496
00497
00498 if (! es_positivo) {
00499 num = -num;
00500 }
00501 set( num, den );
00502 return *this;
00503 }
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513 template <class INT>
00514 ostream& operator<< (ostream &COUT, const rational<INT>& r) {
00515 if ( r.m_den == 1 ) {
00516 return COUT << "[" << r.m_num << "]" ;
00517 } else {
00518 return COUT << "[" << r.m_num << "/" << r.m_den << "]" ;
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 template <class INT>
00532 istream& operator >> (istream &CIN, rational<INT>& r) {
00533 char ch;
00534
00535 bool es_positivo = true;
00536
00537
00538 do {
00539 CIN >> ch;
00540 if (ch == '-') {
00541 es_positivo = !es_positivo;
00542 }
00543 } while (!isdigit(ch));
00544
00545
00546 r.m_num = 0;
00547 while (isdigit(ch)) {
00548 r.m_num = 10 * r.m_num + (ch-'0');
00549 CIN >> ch;
00550 }
00551
00552
00553 while (isspace(ch)) {
00554 CIN >> ch;
00555 }
00556
00557 if (ch ==']') {
00558 r.m_den = 1;
00559 }
00560 else {
00561 do {
00562 CIN >> ch;
00563 if (ch == '-') {
00564 es_positivo = !es_positivo;
00565 }
00566 } while (!isdigit(ch));
00567
00568
00569 r.m_den = 0;
00570 while (isdigit(ch)) {
00571 r.m_den = 10 * r.m_den + (ch-'0');
00572 CIN >> ch;
00573 }
00574
00575
00576
00577
00578 while (ch != ']') {
00579 CIN >> ch;
00580 }
00581 }
00582
00583
00584
00585 if (! es_positivo) {
00586 r.m_num = -r.m_num;
00587 }
00588
00589 r.Simplify();
00590 return CIN;
00591
00592
00593
00594
00595
00596
00597
00598 }
00599
00600
00601
00602 template <class INT>
00603 rational<INT> operator + (const rational<INT> &x, const rational<INT> &y) {
00604 INT res_num, res_den;
00605 res_den = x.m_den * y.m_den;
00606 res_num = x.m_num * y.m_den + x.m_den * y.m_num;
00607
00608 return rational(res_num, res_den);
00609 }
00610
00611
00612
00613 template <class INT>
00614 rational<INT> operator - (const rational<INT> &x, const rational<INT> &y) {
00615 INT res_num, res_den;
00616
00617 res_den = x.m_den * y.m_den;
00618 res_num = x.m_num * y.m_den - x.m_den * y.m_num;
00619
00620 return rational<INT>(res_num, res_den);
00621 }
00622
00623
00624
00625 template <class INT>
00626 rational<INT> operator * (const rational<INT> &x, const rational<INT> &y) {
00627 INT res_num, res_den;
00628
00629 res_num = x.m_num * y.m_num;
00630 res_den = x.m_den * y.m_den;
00631
00632 return rational(res_num, res_den);
00633 }
00634
00635
00636
00637
00638 template <class INT>
00639 rational<INT> operator / (const rational<INT> &x, const rational<INT> &y) {
00640 INT res_num, res_den;
00641 if (0 != y.m_num) {
00642 res_num = x.m_num * y.m_den;
00643 res_den = x.m_den * y.m_num;
00644 }
00645 return rational<INT>(res_num, res_den);
00646 }
00647
00648
00649
00650 #endif // rational_h
00651
00652