campo-sirio/include/fraction.cpp

543 lines
12 KiB
C++
Executable File

#include <stdio.h>
#include <fraction.h>
#include <strings.h>
static __int64 mcd(__int64 a, __int64 b)
{
if (a < 0) a = -a;
if (b < 0) b = -b;
while (b > 0)
{
__int64 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.full())
{
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(",.-+/[]");
sscanf_s(n, "%I64d", &_num);
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.is_zero())
build_fraction("");
else
{
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)
{
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)
{
_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 <gt> | Controlla se un reale e' maggiore di un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' maggiore di <p b>
// @flag FALSE | Se <p a> e' non maggiore di <p b>
bool operator > (
const fraction & a, // @parm Prima frazione da confrontare
const fraction & b) // @parm Seconda frazione da confrontare
// @syntax operator <gt> (const fraction & a, const fraction & b);
// @syntax operator <gt> (const real & a, const fraction &b);
// @syntax operator <gt> (const fraction &a, const real & b);
{
fraction f = a - b;
return f.sign() > 0;
}
// @doc EXTERNAL
// @func bool | operator <lt> | Controlla se un reale e' minore di un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore di <p b>
// @flag FALSE | Se <p a> e' non minore di <p b>
bool operator < (
const fraction & a, // @parm Prima frazione da confrontare
const fraction & b) // @parm Seconda frazione da confrontare
// @syntax operator <lt> (const fraction &a, const fractio &b);
// @syntax operator <lt> (const real & a, const fraction &b);
// @syntax operator <lt> (const fraction &a, const real & b);
{
fraction f = a - b;
return f.sign() < 0;
}
// @doc EXTERNAL
// @func bool | operator <gt>= | Controlla se un reale e' maggiore o uguale ad
// un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' maggiore o uguale a <p b>
// @flag FALSE | Se <p a> e' minore di <p b>
bool operator >= (
const fraction & a, // @parm Prima frazione da confrontare
const fraction & b) // @parm Seconda frazione da confrontare
// @syntax operator <gt>= (const fraction &a, const fractio &b);
// @syntax operator <gt>= (const real & a, const fraction &b);
// @syntax operator <gt>= (const fraction &a, const real & b);
{
fraction f = a - b;
return f.sign() >= 0;
}
// @doc EXTERNAL
// @func bool | operator <lt>= | Controlla se un reale e' minore o uguale ad
// un altro
//
// @rdesc Ritorna i seguenti valori
//
// @flag TRUE | Se <p a> e' minore o uguale a <p b>
// @flag FALSE | Se <p a> e' maggiore di <p b>
bool operator <= (
const fraction & a, // @parm Prima frazione da confrontare
const fraction & b) // @parm Seconda frazione da confrontare
// @syntax operator <lt>= (const fraction &a, const fractio &b);
// @syntax operator <lt>= (const real & a, const fraction &b);
// @syntax operator <lt>= (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 <p a> e' uguale a <p b>
// @flag FALSE | Se <p a> non e' uguale a <p b>
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 <p a> e' diverso da <p b>
// @flag FALSE | Se <p a> e' uguale a <p b>
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 <p a> con la frazione <p b>
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 <p a> e <p b>
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 <p a> e <p b>
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;
}