00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #ifndef rational_h
00019 #define rational_h ///< Evita la inclusión múltiple
00020
00021
00022 namespace std { }
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 public:
00040
00041
00042 rational() : m_num(INT(0)), m_den(INT(1)) { }
00043 rational(INT num) : m_num(num), m_den(INT(1)) { }
00044 rational(INT num, INT den)
00045 : m_num(num), m_den(den) { simplify(); }
00046
00047 rational(const rational& o) { m_num = o.m_num; m_den = o.m_den; }
00048 ~rational() { }
00049
00050 void set( const INT& n=INT(0), const INT& d=INT(1) );
00051
00052
00053
00054
00055
00056
00057 const INT& num() const { return m_num; }
00058
00059 const INT& den() const { return m_den; }
00060
00061
00062
00063
00064 rational& operator= (const rational&);
00065 rational& operator= (INT);
00066 rational& swap ( rational& );
00067
00068 rational& operator+=( const rational& );
00069 rational& operator-=( const rational& );
00070 rational& operator*=( const rational& );
00071 rational& operator/=( const rational& );
00072
00073 rational operator-() const;
00074
00075
00076 template <class NUM> friend rational<NUM> operator+( const rational<NUM>&, const rational<NUM>& );
00077 template <class NUM> friend rational<NUM> operator-( const rational<NUM>&, const rational<NUM>& );
00078 template <class NUM> friend rational<NUM> operator*( const rational<NUM>&, const rational<NUM>& );
00079 template <class NUM> friend rational<NUM> operator/( const rational<NUM>&, const rational<NUM>& );
00080
00081 template <class NUM> friend bool operator==( const rational<NUM>&, const rational<NUM>& );
00082 template <class NUM> friend bool operator<( const rational<NUM>&, const rational<NUM>& );
00083 template <class NUM> friend bool operator!=( const rational<NUM>&, const rational<NUM>& );
00084 template <class NUM> friend bool operator<=( const rational<NUM>&, const rational<NUM>& );
00085 template <class NUM> friend bool operator>=( const rational<NUM>&, const rational<NUM>& );
00086 template <class NUM> friend bool operator>( const rational<NUM>&, const rational<NUM>& );
00087
00088 template <class NUM> friend rational<NUM>& operator++( rational<NUM> & r );
00089 template <class NUM> friend rational<NUM> operator++( rational<NUM> & r , int );
00090 template <class NUM> friend rational<NUM>& operator--( rational<NUM> & r );
00091 template <class NUM> friend rational<NUM> operator--( rational<NUM> & r , int );
00092
00093 template <class NUM> friend ostream& operator<< (ostream &, const rational<NUM>& );
00094 template <class NUM> friend istream& operator>> (istream &, rational<NUM>& );
00095 rational& fromString (const char* nStr);
00096
00097 template <class NUM> friend double real (const rational<NUM>& );
00098 template <class NUM> friend long integer(const rational<NUM>& );
00099
00100 template <class NUM> friend bool check_ok( const rational<NUM>& r );
00101
00102
00103
00104 template <class NUM> friend class test_rational;
00105 };
00106
00107 template <class NUM>
00108 NUM mcd(NUM x, NUM y);
00109
00110
00111 template <class INT>
00112 inline INT gcd( const INT& x, const INT& y ) { return mcd(x,y); }
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 template <class INT>
00123 inline void rational<INT>::set( const INT& n, const INT& d ) {
00124 m_num = n;
00125 #ifdef NDEBUG
00126 m_den = d;
00127 #else
00128 if ( d==INT(0) ) {
00129 m_den = INT(1);
00130 }
00131 else {
00132 m_den = d;
00133 }
00134 #endif
00135 simplify();
00136 }
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 template <class INT>
00152 inline rational<INT>& rational<INT>::operator=( const rational<INT>& o ) {
00153 m_num = o.m_num,
00154 m_den = o.m_den;
00155
00156
00157 return *this;
00158 }
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171 template <class INT>
00172 inline rational<INT>& rational<INT>::swap( rational<INT>& o ) {
00173 #if 1
00174 rational tmp = o;
00175 o = *this;
00176 *this = tmp;
00177 #else
00178
00179 char tmp[ sizeof( *this ) ];
00180 memcpy( tmp, & o, sizeof( *this ) );
00181 memcpy( & o, this, sizeof( *this ) );
00182 memcpy( this, tmp, sizeof( *this ) );
00183
00184 #endif
00185 return *this;
00186 }
00187
00188
00189
00190
00191
00192
00193
00194 template <class INT>
00195 inline rational<INT>& rational<INT>::operator= ( INT entero ) {
00196 m_num = entero;
00197 m_den = 1;
00198 return *this;
00199 }
00200
00201
00202
00203
00204
00205
00206
00207 template <class INT>
00208 inline rational<INT>& rational<INT>::operator*=( const rational<INT>& num ) {
00209 m_num *= num.m_num;
00210 m_den *= num.m_den;
00211 simplify();
00212 return *this;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 template <class INT>
00224 inline rational<INT>& rational<INT>::operator/=( const rational<INT>& num ) {
00225 m_num *= num.m_den;
00226 m_den *= num.m_num;
00227 simplify();
00228 return *this;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 template <class INT>
00241 inline rational<INT> rational<INT>::operator-() const {
00242 rational tmp = (*this);
00243 tmp.m_num = - tmp.m_num;
00244 return tmp;
00245 }
00246
00247
00248
00249
00250
00251
00252
00253 template <class NUM>
00254 inline bool operator==( const rational<NUM> &x, const rational<NUM> &y ) {
00255 return (x.m_num == y.m_num) && (x.m_den == y.m_den);
00256
00257
00258
00259
00260
00261
00262 }
00263
00264
00265 template <class NUM>
00266 inline bool operator<( const rational<NUM> &x, const rational<NUM> &y ) {
00267 return (x.m_num * y.m_den) < (x.m_den * y.m_num);
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285 }
00286
00287
00288 template <class NUM>
00289 inline bool operator>( const rational<NUM> &x, const rational<NUM> &y ) {
00290 return (y < x);
00291 }
00292
00293
00294 template <class NUM>
00295 inline bool operator!=( const rational<NUM>& x, const rational<NUM>& y ) {
00296 return !(x == y);
00297 }
00298
00299
00300 template <class NUM>
00301 inline bool operator<=( const rational<NUM>& x, const rational<NUM>& y ) {
00302 return !(y < x);
00303 }
00304
00305
00306 template <class NUM>
00307 inline bool operator>=( const rational<NUM>& x, const rational<NUM>& y ) {
00308 return !(x < y);
00309 }
00310
00311
00312 template <class NUM>
00313 inline double real(const rational<NUM>& num) {
00314 return double (num.m_num) / double (num.m_den);
00315 }
00316
00317
00318 template <class NUM>
00319 inline long integer(const rational<NUM>& num) {
00320 return long ( num.m_num / num.m_den );
00321 }
00322
00323 #if 0
00324
00325 template <class NUM>
00326 inline rational<NUM>::operator NUM() {
00327 return NUM (m_num / m_den);
00328 }
00329 #endif
00330
00331 #include <cstdlib>
00332 #include <cctype>
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355 template <class NUM>
00356 bool check_ok( const rational<NUM>& r ) {
00357 if ( &r != 0 ) {
00358
00359 }
00360 else {
00361
00362 return false;
00363 }
00364
00365 if ( r.m_den > 0 ) {
00366
00367 }
00368 else {
00369
00370 return false;
00371 }
00372 if (r.m_num == 0) {
00373 if ( r.m_den == 1 ) {
00374
00375 return true;
00376 }
00377 else {
00378 return false;
00379 }
00380 }
00381 if ( mcd(r.m_num, r.m_den) == 1 ) {
00382
00383 }
00384 else {
00385
00386 return false;
00387 }
00388 return true;
00389 }
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 template <class NUM>
00401 bool check_ok_no_Rep( const rational<NUM>& r ) {
00402 if ( ! (&r != 0) ) {
00403
00404 return false;
00405 }
00406
00407 if ( ! (r.den() > 0) ) {
00408
00409 return false;
00410 }
00411 if (r.num() == 0) {
00412 if ( r.den() == 1 ) {
00413
00414 return true;
00415 }
00416 else {
00417 return false;
00418 }
00419 }
00420 if ( ! ( mcd(r.num(), r.den()) == 1 ) ) {
00421
00422 return false;
00423 }
00424 return true;
00425 }
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448 template <class NUM>
00449 NUM mcd(NUM x, NUM y) {
00450 NUM g = (x < 0 ? -x : x);
00451 NUM r = (y < 0 ? -y : y);
00452 NUM temp;
00453
00454 do {
00455 temp = r;
00456 r = g % r;
00457 g = temp;
00458 } while (NUM(0) != r);
00459
00460 return g;
00461 }
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478 template <class NUM>
00479 void rational<NUM>::simplify() {
00480 if (m_num == 0) {
00481 m_den = 1;
00482 return;
00483 }
00484 NUM divisor = mcd(m_num, m_den);
00485 if (divisor > 1) {
00486 m_num /= divisor;
00487 m_den /= divisor;
00488 }
00489 if (m_den < 0) {
00490 m_num = -m_num;
00491 m_den = -m_den;
00492 }
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 template <class INT>
00502 rational<INT>& rational<INT>::operator+=( const rational<INT>& otro ) {
00503 m_num = m_num * otro.m_den + m_den * otro.m_num;
00504 m_den *= otro.m_den;
00505 simplify();
00506 return *this;
00507 }
00508
00509
00510
00511
00512
00513
00514
00515 template <class INT>
00516 rational<INT>& rational<INT>::operator-=( const rational<INT>& otro ) {
00517 INT oldm_den = m_den;
00518 INT oldm_num = m_num;
00519 INT d = otro.m_den;
00520 INT n = otro.m_num;
00521
00522 m_den *= d;
00523 m_num = oldm_num * d - oldm_den * n;
00524 simplify();
00525
00526 return *this;
00527 }
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542 template <class NUM>
00543 ostream& operator<<( ostream &COUT, const rational<NUM>& r ) {
00544 if ( r.m_den == 1 ) {
00545 return COUT << "[" << r.m_num << "]" ;
00546 } else {
00547 return COUT << "[" << r.m_num << "/" << r.m_den << "]" ;
00548 }
00549 }
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565 template <class NUM>
00566 istream& operator>>( istream &CIN, rational<NUM>& r ) {
00567 char ch;
00568 const NUM DIEZ = 10;
00569
00570 bool es_positivo = true;
00571
00572
00573 do {
00574 CIN >> ch;
00575 if (ch == '-') {
00576 es_positivo = !es_positivo;
00577 }
00578 } while (!isdigit(ch));
00579
00580
00581 r.m_num = 0;
00582 while (isdigit(ch)) {
00583 r.m_num = DIEZ * r.m_num + (ch-'0');
00584 CIN >> ch;
00585 }
00586
00587
00588 while (isspace(ch)) {
00589 CIN >> ch;
00590 }
00591
00592 if (ch ==']') {
00593 r.m_den = 1;
00594 }
00595 else {
00596 do {
00597 CIN >> ch;
00598 if (ch == '-') {
00599 es_positivo = !es_positivo;
00600 }
00601 } while (!isdigit(ch));
00602
00603
00604 r.m_den = 0;
00605 while (isdigit(ch)) {
00606 r.m_den = DIEZ * r.m_den + (ch-'0');
00607 CIN >> ch;
00608 }
00609
00610
00611
00612
00613 while (ch != ']') {
00614 CIN >> ch;
00615 }
00616 }
00617
00618
00619
00620 if (! es_positivo) {
00621 r.m_num = -r.m_num;
00622 }
00623 #ifndef NDEBUG
00624 if ( r.m_den == NUM(0) ) {
00625 r.m_den = 1;
00626 }
00627 #endif
00628
00629 r.simplify();
00630 return CIN;
00631
00632
00633
00634
00635
00636
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647 template <class NUM>
00648 rational<NUM>& rational<NUM>::fromString (const char* nStr) {
00649 char ch;
00650 const NUM DIEZ = NUM(10);
00651
00652 bool es_positivo = true;
00653
00654
00655 do {
00656 ch = *nStr; nStr++;
00657 if (ch == '-') {
00658 es_positivo = !es_positivo;
00659 }
00660 } while (!isdigit(ch));
00661
00662
00663 NUM num = NUM(0);
00664 while (isdigit(ch)) {
00665 num = DIEZ * num + NUM(ch-'0');
00666 ch = *nStr; nStr++;
00667 }
00668
00669
00670 while (isspace(ch)) {
00671 ch = *nStr; nStr++;
00672 }
00673
00674 NUM den;
00675 if (ch ==']') {
00676 den = NUM(1);
00677 }
00678 else {
00679 do {
00680 ch = *nStr; nStr++;
00681 if (ch == '-') {
00682 es_positivo = !es_positivo;
00683 }
00684 } while (!isdigit(ch));
00685
00686
00687 den = NUM(0);
00688 while (isdigit(ch)) {
00689 den = DIEZ * den + NUM(ch-'0');
00690 ch = *nStr; nStr++;
00691 }
00692
00693 }
00694
00695
00696 if (! es_positivo) {
00697 num = -num;
00698 }
00699 set( num, den );
00700 return *this;
00701 }
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711 template <class NUM>
00712 rational<NUM> operator + (const rational<NUM> &x, const rational<NUM> &y) {
00713 NUM res_num, res_den;
00714 res_den = x.m_den * y.m_den;
00715 res_num = x.m_num * y.m_den + x.m_den * y.m_num;
00716
00717 return rational<NUM>(res_num, res_den);
00718 }
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728 template <class NUM>
00729 rational<NUM> operator-( const rational<NUM> &x, const rational<NUM> &y ) {
00730 NUM res_num, res_den;
00731 res_den = x.m_den * y.m_den;
00732 res_num = x.m_num * y.m_den - x.m_den * y.m_num;
00733
00734 return rational<NUM>(res_num, res_den);
00735 }
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 template <class NUM>
00746 rational<NUM> operator*( const rational<NUM> &x, const rational<NUM> &y ) {
00747 NUM res_num, res_den;
00748 res_num = x.m_num * y.m_num;
00749 res_den = x.m_den * y.m_den;
00750
00751 return rational<NUM>(res_num, res_den);
00752 }
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 template <class NUM>
00764 rational<NUM> operator/( const rational<NUM> &x, const rational<NUM> &y ) {
00765 NUM res_num, res_den;
00766 #ifdef NDEBUG
00767 res_num = x.m_num * y.m_den;
00768 res_den = x.m_den * y.m_num;
00769 return rational<NUM>(res_num, res_den);
00770 #else
00771 if (NUM(0) != y.m_num) {
00772 res_num = x.m_num * y.m_den;
00773 res_den = x.m_den * y.m_num;
00774 return rational<NUM>(res_num, res_den);
00775 }
00776 else {
00777 return rational<NUM>(NUM(0),NUM(1));
00778 }
00779 #endif
00780 }
00781
00782
00783
00784
00785
00786
00787
00788 template <class NUM>
00789 inline rational<NUM>& operator++( rational<NUM> & r ) {
00790 r += rational<NUM>(NUM(1));
00791 return r;
00792 }
00793
00794
00795 template <class NUM>
00796 inline rational<NUM> operator++( rational<NUM> & r , int ) {
00797 rational<NUM> tmp = r;
00798 r += rational<NUM>(NUM(1));
00799 return tmp;
00800 }
00801
00802
00803
00804
00805
00806
00807
00808 template <class NUM>
00809 inline rational<NUM>& operator--( rational<NUM> & r ) {
00810 r -= rational<NUM>(NUM(1));
00811 return r;
00812 }
00813
00814
00815 template <class NUM>
00816 inline rational<NUM> operator--( rational<NUM> & r , int ) {
00817 rational<NUM> tmp = r;
00818 r -= rational<NUM>(NUM(1));
00819 return tmp;
00820 }
00821
00822 #endif // rational_h
00823
00824