#include #include static __int64 mcd(__int64 a, __int64 b) { if (a < 0) a = -a; if (b < 0) b = -b; __int64 r; while (b > 0) { r = a % b; a = b; b = r; } return a; } static __int64 mcm(__int64 a, __int64 b) { if (a < 0) a = -a; if (b < 0) b = -b; return ((a * b) / mcd(a, b)); } void fraction::simplify() { if (_den > 1 && _num > 1) { __int64 div = mcd(_num, _den); if (div > 1) { _num /= div; _den /= div; } } if (_den < 0) { _num = -_num; _den = -_den; } } // Crea una frazione a partire da una stringa avente la VIRGOLA come separatore dei decimali! void fraction::build_fraction (const char *s) { TString80 n = s; _num = 0; _den = 1; if (n.not_empty()) { int pdec = n.find(','); const int psqr = n.find('['), psls = n.find('/'); int ndec = 0, len_periodo = 0, sign = 1, anti_periodo = 0; if (pdec < 0) pdec = n.find('.'); if (n.find('-') >= 0) sign = -1; if (pdec >= 0) ndec = n.len() - pdec - 1; if (psls > 0) { TString80 num = n.left(psls); fraction a(num); num = n.mid(psls + 1); fraction b(num); *this = a / b; return; } if (psqr > 0) { int end = n.find(']'); if (end < psqr) end = n.len(); len_periodo = end - psqr - 1; anti_periodo = psqr -pdec - 1; } else if (ndec > 2) { bool found = FALSE; int j = 0; const char * pc; for (pc = (const char *)n + pdec + 1; !found && *pc != '\0'; pc++) { int max_period = strlen(pc) / 3; for (j = max_period; !found && j > 0 ; j--) { int len = 0, pos = 0, c; for (c = 0; c < j; c++) { const char * pp = pc + c; len = strlen(pp); char cmp = *pp; pos = 0; while (pos < len) { if (pp[pos] != cmp) if (pos < len - 1 || (pp[pos] - cmp) != 1 || *(pp + 1) < '5') break; pos += j; } if (pos < len) break; } found = (pos == len) && (c == (len + 1) % j + 1); } if (!found) anti_periodo++; } if (found) { len_periodo = j + 1; n.cut(pdec + anti_periodo + len_periodo + 1); } } n.strip(",.-+/[]"); #ifdef WIN32 sscanf(n, "%I64d", &_num); #else sscanf(n, "%Ld", &_num); #endif if (len_periodo > 0) { _den = 9; __int64 sub = _num / 10; for (int l = len_periodo - 1; l > 0 ; l--) { _den = (_den * 10) + 9; sub /= 10; } if (anti_periodo > 0) for (int p = anti_periodo; p > 0; p--) _den *= 10; _num -= sub; } else for (int p = ndec; p > 0; p--) _den *= 10; _num *= sign; } simplify(); } fraction::fraction() { _num = 0; _den = 1; } fraction::fraction(const fraction& b) { _num = b._num; _den = b._den; } fraction::fraction(const real& num, const real& den) { if (den == UNO) build_fraction(num.stringa()); else { real n = num; n /= den; build_fraction(n.stringa()); } } int fraction::sign() const { if ( _num == 0 || _den == 0) return 0; return _num < 0 ? (_den < 0 ? +1 : -1) : (_den < 0 ? -1 : +1); } fraction& fraction::operator =(const fraction & b) { _num = b._num; _den = b._den; return *this; } fraction& fraction::operator += (const fraction & b) { const __int64 m = mcm(_den, b._den); _num = _num * ( m / _den) + b._num * ( m / b._den); _den = m; simplify(); return *this; } fraction& fraction::operator -= (const fraction & b) { __int64 m = mcm(_den, b._den); _num = _num * ( m / _den) - b._num * ( m / b._den); _den = m; simplify(); return *this; } fraction& fraction::operator *= (const fraction & b) { _num = _num * b._num; _den = _den * b._den; simplify(); return *this; } fraction& fraction::operator /= (const fraction & b) { _num = _num * b._den; _den = _den * b._num; simplify(); return *this; } fraction fraction::operator - () const { fraction b(*this); b._num = -b._num; return b; } // Funzioni comuni dei due real TObject* fraction::dup () const { return new fraction(*this); } fraction::operator real() const { real n, d; n.set_int64(_num); d.set_int64(_den); real q = n; q /= d; return q; } // @doc EXTERNAL // @func real | operator + | Somma due numeri reali // // @rdesc Ritorna il valore della somma fraction operator + ( const fraction & a, // @parm Primo addendo da sommare const fraction & b) // @parm Secondo addendo da sommare // @syntax operator +(const fraction & a, const fraction & b); // @syntax operator +(const real & a, const fraction & b); // @syntax operator +(const fraction & a, const real & b); { fraction f = a; f += b; return f; } // @doc EXTERNAL // @func real | operator - | Sottrae due numeri reali // // @rdesc Ritorna il valore della sottrazione fraction operator - ( const fraction & a, // @parm Primo addendo da sottrarre const fraction & b) // @parm Secondo addendo da sottrarre // @syntax operator -(const fraction & a, const fraction & b); // @syntax operator -(const real & a, const fraction & b); // @syntax operator -(const fraction & a, const real & b); { fraction f = a; f -= b; return f; } // @doc EXTERNAL // @func real | operator * | Moltiplica due frazioni // // @rdesc Ritorna il valore della moltiplicazione fraction operator *( const fraction & a, // @parm Prima frazione da moltiplicare const fraction & b) // @parm Seconda frazione da moltiplicare // @syntax operator *(const fraction & a, const fraction & b); // @syntax operator *(const real & a, const fraction & b); // @syntax operator *(const fraction & a, const real & b); { fraction f = a; f *= b; return f; } // @doc EXTERNAL // @func real | operator * | Moltiplica una frazione e un intero // // @rdesc Ritorna il valore della moltiplicazione fraction operator *( const fraction & a, // @parm frazione da moltiplicare __int64 b) // @parm intero da moltiplicare // @syntax operator -(__int64 a, const fraction & b); // @syntax operator -(const fraction & a, __int64 b); { fraction f; f._num = a._num * b; f._den = a._den; f.simplify(); return f; } // @doc EXTERNAL // @func real | operator / | Divide due frazioni // // @rdesc Ritorna il valore della divisione fraction operator / ( const fraction & a, // @parm Prima frazione da dividere const fraction & b) // @parm Seconda frazione da dividere // @syntax operator /(const fraction & a, const fraction & b); // @syntax operator /(const real & a, const fraction & b); // @syntax operator /(const fraction & a, const real & b); { fraction f = a; f /= b; return f; } // @doc EXTERNAL // @func real | operator * | Divide una frazione per un intero // // @rdesc Ritorna il valore della divisione fraction operator /( const fraction & a, // @parm frazione da dividere __int64 b) // @parm intero divisore // @syntax operator /(const fraction & a, __int64 b); { fraction f; f._num = a._num; f._den = a._den * b; f.simplify(); return f; } // @doc EXTERNAL // @func real | operator * | Divide una frazione per un intero // // @rdesc Ritorna il valore della divisione fraction operator /( __int64 a, // @parm intero da dividere const fraction & b) // @parm frazione divisore // @syntax operator /(__int64 a, const fraction & b); { fraction f; f._num = b._den * a; f._den = b._num ; f.simplify(); return f; } // @doc EXTERNAL // @func bool | operator | Controlla se un reale e' maggiore di un altro // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' maggiore di

// @flag FALSE | Se

e' non maggiore di

bool operator > ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator (const fraction & a, const fraction & b); // @syntax operator (const real & a, const fraction &b); // @syntax operator (const fraction &a, const real & b); { fraction f = a - b; return f.sign() > 0; } // @doc EXTERNAL // @func bool | operator | Controlla se un reale e' minore di un altro // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' minore di

// @flag FALSE | Se

e' non minore di

bool operator < ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator (const fraction &a, const fractio &b); // @syntax operator (const real & a, const fraction &b); // @syntax operator (const fraction &a, const real & b); { fraction f = a - b; return f.sign() < 0; } // @doc EXTERNAL // @func bool | operator = | Controlla se un reale e' maggiore o uguale ad // un altro // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' maggiore o uguale a

// @flag FALSE | Se

e' minore di

bool operator >= ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator = (const fraction &a, const fractio &b); // @syntax operator = (const real & a, const fraction &b); // @syntax operator = (const fraction &a, const real & b); { fraction f = a - b; return f.sign() >= 0; } // @doc EXTERNAL // @func bool | operator = | Controlla se un reale e' minore o uguale ad // un altro // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' minore o uguale a

// @flag FALSE | Se

e' maggiore di

bool operator <= ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator = (const fraction &a, const fractio &b); // @syntax operator = (const real & a, const fraction &b); // @syntax operator = (const fraction &a, const real & b); { fraction f = a - b; return f.sign() <= 0; } // @doc EXTERNAL // @func bool | operator == | Controlla se un reale e' uguale ad un altro // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' uguale a

// @flag FALSE | Se

non e' uguale a

bool operator == ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator == (const fraction &a, const fractio &b); // @syntax operator == (const real & a, const fraction &b); // @syntax operator == (const fraction &a, const real & b); { fraction f = a - b; return f.sign() == 0; } // @doc EXTERNAL // @func bool | operator != | Controlla se 2 reali dono diversi // // @rdesc Ritorna i seguenti valori // // @flag TRUE | Se

e' diverso da

// @flag FALSE | Se

e' uguale a

bool operator != ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax operator != (const fraction &a, const fractio &b); // @syntax operator != (const real & a, const fraction &b); // @syntax operator != (const fraction &a, const real & b); { return ! ::operator ==(a, b); } // @doc EXTERNAL // @func Scambia la frazione

con la frazione

void swap ( fraction & a, // @parm Prima frazione da scambiare fraction & b) // @parm Seconda frazione da scambiare { fraction f = a; a = b; b = f; } // @doc EXTERNAL // @func Ritorna il numero reale piu' piccolo tra

e

const fraction& fnc_min ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax const real& fnc_min (const fraction & a, const fraction & b) { return a < b ? a : b; } // @doc EXTERNAL // @func Ritorna il numero reale piu' grande tra

e

const fraction& fnc_max ( const fraction & a, // @parm Prima frazione da confrontare const fraction & b) // @parm Seconda frazione da confrontare // @syntax const real& fnc_max (const fraction & a, const fraction & b) { return a > b ? a : b; }