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