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