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
00067 template <class T>
00068 friend rational<T> operator + (const rational<T>&, const rational<T>&);
00069 template <class T>
00070 friend rational<T> operator - (const rational<T>&, const rational<T>&);
00071 template <class T>
00072 friend rational<T> operator * (const rational<T>&, const rational<T>&);
00073 template <class T>
00074 friend rational<T> operator / (const rational<T>&, const rational<T>&);
00075
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 template <class T>
00087 friend bool operator > (const rational<T>&, const rational<T>&);
00088
00089 template <class T> friend ostream& operator << (ostream &, const rational& );
00090 template <class T> friend istream& operator >> (istream &, rational& );
00091 rational& fromString (const char* nStr);
00092
00093 template <class T>
00094 friend double real (const rational& );
00095 template <class T>
00096 friend INT integer(const rational& );
00097
00098 template <class T>
00099 friend bool check_ok( const rational& 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<INT>& 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<INT>& 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<INT>& 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 template <class INT>
00272 inline rational<INT>::operator INT() {
00273 return INT (m_num / m_den);
00274 }
00275 #endif
00276
00277 template <class INT>
00278 bool check_ok_externo( const rational<INT>& r );
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 #include <cstdlib>
00294 #include <cctype>
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311 template <class INT>
00312 bool check_ok( const rational<INT>& r ) {
00313 if (&r == 0) {
00314
00315 return false;
00316 }
00317
00318 if ( ! (r.m_den > 0) ) {
00319
00320 return false;
00321 }
00322 if (r.m_num == 0) {
00323 if ( r.m_den == 1 ) {
00324
00325 return true;
00326 }
00327 else {
00328 return false;
00329 }
00330 }
00331 if ( ! ( mcd(r.m_num, r.m_den) == 1 ) ) {
00332
00333 return false;
00334 }
00335 return true;
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 template <class INT>
00348 bool check_ok_no_Rep( const rational<INT>& r ) {
00349 if (&r == 0) {
00350
00351 return false;
00352 }
00353
00354 if ( ! (r.den() > 0) ) {
00355
00356 return false;
00357 }
00358 if (r.num() == 0) {
00359 if ( r.den() == 1 ) {
00360
00361 return true;
00362 }
00363 else {
00364 return false;
00365 }
00366 }
00367 if ( ! ( mcd(r.num(), r.den()) == 1 ) ) {
00368
00369 return false;
00370 }
00371 return true;
00372 }
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391 template <class INT>
00392 INT mcd(INT x, INT y) {
00393 INT g = (x < 0 ? -x : x);
00394 INT r = (y < 0 ? -y : y);
00395 INT temp;
00396
00397 do {
00398 temp = r;
00399 r = g % r;
00400 g = temp;
00401 } while (0 != r);
00402
00403 return g;
00404 }
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 template <class INT>
00418 void rational<INT>::Simplify() {
00419 if (m_num == 0) {
00420 m_den = 1;
00421 }
00422 INT divisor = mcd(m_num, m_den);
00423 if (divisor > 1) {
00424 m_num /= divisor;
00425 m_den /= divisor;
00426 }
00427 if (m_den < 0) {
00428 m_num = -m_num;
00429 m_den = -m_den;
00430 }
00431 }
00432
00433
00434 template <class INT>
00435 rational<INT>& rational<INT>::operator += (const rational<INT>& otro) {
00436 m_num = m_num * otro.m_den + m_den * otro.m_num;
00437 m_den *= otro.m_den;
00438 Simplify();
00439
00440 return *this;
00441 }
00442
00443
00444
00445 template <class INT>
00446 rational<INT>& rational<INT>::operator -= (const rational<INT>& otro) {
00447 INT oldm_den = m_den;
00448 INT oldm_num = m_num;
00449 INT d = otro.m_den;
00450 INT n = otro.m_num;
00451
00452 m_den *= d;
00453 m_num = oldm_num * d - oldm_den * n;
00454 Simplify();
00455
00456 return *this;
00457 }
00458
00459
00460
00461 template <class INT>
00462 rational<INT>& rational<INT>::fromString (const char* nStr) {
00463 char ch;
00464
00465 bool es_positivo = true;
00466
00467
00468 do {
00469 ch = *nStr; nStr++;
00470 if (ch == '-') {
00471 es_positivo = !es_positivo;
00472 }
00473 } while (!isdigit(ch));
00474
00475
00476 INT num = 0;
00477 while (isdigit(ch)) {
00478 num = 10 * num + (ch-'0');
00479 ch = *nStr; nStr++;
00480 }
00481
00482
00483 while (isspace(ch)) {
00484 ch = *nStr; nStr++;
00485 }
00486
00487 INT den;
00488 if (ch ==']') {
00489 den = 1;
00490 }
00491 else {
00492 do {
00493 ch = *nStr; nStr++;
00494 if (ch == '-') {
00495 es_positivo = !es_positivo;
00496 }
00497 } while (!isdigit(ch));
00498
00499
00500 den = 0;
00501 while (isdigit(ch)) {
00502 den = 10 * den + (ch-'0');
00503 ch = *nStr; nStr++;
00504 }
00505
00506 }
00507
00508
00509
00510 if (! es_positivo) {
00511 num = -num;
00512 }
00513 set( num, den );
00514 return *this;
00515 }
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525 template <class INT>
00526 ostream& operator<< (ostream &COUT, const rational<INT>& r) {
00527 if ( r.m_den == 1 ) {
00528 return COUT << "[" << r.m_num << "]" ;
00529 } else {
00530 return COUT << "[" << r.m_num << "/" << r.m_den << "]" ;
00531 }
00532 }
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 template <class INT>
00544 istream& operator >> (istream &CIN, rational<INT>& r) {
00545 char ch;
00546
00547 bool es_positivo = true;
00548
00549
00550 do {
00551 CIN >> ch;
00552 if (ch == '-') {
00553 es_positivo = !es_positivo;
00554 }
00555 } while (!isdigit(ch));
00556
00557
00558 r.m_num = 0;
00559 while (isdigit(ch)) {
00560 r.m_num = 10 * r.m_num + (ch-'0');
00561 CIN >> ch;
00562 }
00563
00564
00565 while (isspace(ch)) {
00566 CIN >> ch;
00567 }
00568
00569 if (ch ==']') {
00570 r.m_den = 1;
00571 }
00572 else {
00573 do {
00574 CIN >> ch;
00575 if (ch == '-') {
00576 es_positivo = !es_positivo;
00577 }
00578 } while (!isdigit(ch));
00579
00580
00581 r.m_den = 0;
00582 while (isdigit(ch)) {
00583 r.m_den = 10 * r.m_den + (ch-'0');
00584 CIN >> ch;
00585 }
00586
00587
00588
00589
00590 while (ch != ']') {
00591 CIN >> ch;
00592 }
00593 }
00594
00595
00596
00597 if (! es_positivo) {
00598 r.m_num = -r.m_num;
00599 }
00600
00601 r.Simplify();
00602 return CIN;
00603
00604
00605
00606
00607
00608
00609
00610 }
00611
00612
00613
00614 template <class INT>
00615 rational<INT> operator + (const rational<INT> &x, const rational<INT> &y) {
00616 INT res_num, res_den;
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_den = x.m_den * y.m_den;
00630 res_num = x.m_num * y.m_den - x.m_den * y.m_num;
00631
00632 return rational<INT>(res_num, res_den);
00633 }
00634
00635
00636
00637 template <class INT>
00638 rational<INT> operator * (const rational<INT> &x, const rational<INT> &y) {
00639 INT res_num, res_den;
00640
00641 res_num = x.m_num * y.m_num;
00642 res_den = x.m_den * y.m_den;
00643
00644 return rational<INT>(res_num, res_den);
00645 }
00646
00647
00648
00649
00650 template <class INT>
00651 rational<INT> operator / (const rational<INT> &x, const rational<INT> &y) {
00652 INT res_num, res_den;
00653 if (0 != y.m_num) {
00654 res_num = x.m_num * y.m_den;
00655 res_den = x.m_den * y.m_num;
00656 }
00657 return rational<INT>(res_num, res_den);
00658 }
00659
00660
00661
00662
00663 #endif// rational_h
00664
00665