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