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