#include #include #include HIDDEN char __string[128]; const real ZERO (0.0); #ifdef __LONGDOUBLE__ #include #include // @doc EXTERNAL real::real () : _dec(0.0) { } real::real (const real& b) : _dec(b._dec) { } real::real (long double a) : _dec(a) { } bool real::is_real (const char *s) { if (s && *s) { const long double n = _atold(s); if (n == 0.0) { for(; *s; s++) if (*s != '0' && *s != ' ' && *s != '.') return FALSE; } } return TRUE; } real::real (const char *s) { _dec = (s && *s) ? _atold(s) : 0.0; } real& real::operator = (const real& b) { _dec = b._dec; return *this; } real& real::operator = (long double b) { _dec = b; return *this; } real& real::operator += (long double b) { _dec += b; return *this; } real& real::operator -= (long double b) { _dec -= b; return *this; } real& real::operator *= (long double b) { _dec *= b; return *this; } real& real::operator /= (long double b) { _dec /= b; return *this; } // @mfunc Ritorna il segno del reale // // @rdesc Ritorna i seguenti valori: // // @flag 0 | Se il numero e' minore di 0 // @flag = 0 | Se il numero e' uguale a 0 // @flag 0 | Se il numero e' maggiore di 0 int real::sign () const { const int s = _dec > 0.0 ? +1 : (_dec < 0.0 ? -1 : 0); return s; } real real::operator - () const { real n(-_dec); return n; } long real::integer () const { return (long)floorl(_dec); } // Certified 91% // @mfunc Trasforma un reale in stringa // // @rdesc Ritorna la stringa nella lunghezza richiesta char *real::string ( int len, // @parm Lunghezza della stringa (compreso decimali) int dec, // @parm Numero di decimali (default UNDEFINED) char pad) const // @parm Carattere di riempimento (default ' ') // @parm char * | picture | Formato della stringa // @syntax string (int len, int dec, char pad); // @syntax string (const char *picture); // // @comm Nel primo caso ritorna una stringa lunga

con

decimali e // inserisce nella stringa stessa il carattere

nel caso la // lunghezza richiesta sia maggiore di quella che risulterebbe per la // completa rappresentazione del reale. // Nel secondo caso ritorna la stringa con il formato stabilito in //

. { TString16 fmt("%"); if (pad != ' ') fmt << '0'; if (len != 0) fmt << len; if (dec != UNDEFINED) fmt << '.' << dec; fmt << "Lf"; sprintf(__string, fmt, _dec); if (len == 0 && dec == UNDEFINED && strchr(__string, '.') != NULL) { int cut = strlen (__string); for (int i = cut-1; i >= 0; i--) { if (__string[i] == '0') cut--; else { if(__string[i] == '.') cut--; break; } } __string[cut] = '\0'; } return __string; } // Childish algorithm faster and more accurate than powl(10.0, pow) HIDDEN long double ipow10(int pow) { long double n = 1.0; if (pow > 0) { for (int i = pow; i > 0; i--) n *= 10.0; } else { for (int i = pow; i < 0; i++) n *= 0.1; } return n; } // @mfunc real& | real | round | Arrotonda al numero di decimali passati real& real::round ( int prec) // @parm Numero di decimali a cui arrotondare il numero (default 0) // @comm Nel caso

sia: // // @flag 0 | Arrotonda al decimale // @flag = 0 | Arrotonda all'intero // @flag 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille) { long double p = 1.0; if (prec != 0) { p = ipow10(prec); _dec *= p; } _dec = floorl(_dec + 0.5); if (prec != 0) _dec /= p; return *this; } real& real::ceil (int prec) { long double p = 1.0; if (prec != 0) { p = ipow10(prec); _dec *= p; } _dec = ceill(_dec); if (prec != 0) _dec /= p; return *this; } real& real::trunc(int prec) { long double p = 1.0; if (prec != 0) { p = ipow10(prec); _dec *= p; } _dec = floorl(_dec); if (prec != 0) _dec /= p; return *this; } // @func Scambia il numero reale

con il numero real

void swap ( real& a, // @parm Primo numero da scambiare real& b) // @parm Secondo numero da scambiare { const real n = a; a = b; b = n; } long double operator%(const real& a, const real& b) { const long double times = floorl(a / b); const long double resto = a - b * times; return resto; } long double sqrt(long double a) { return sqrtl(a); } long double sqr(long double a) { return a*a; } long double exp10(long double a) { return powl(10.0, a); } long double pow(long double a, long double b) { return powl(a, b); } long double exp(long double a) { return expl(a); } long double log10(long double a) { return log10l(a); } long double log(long double a) { return logl(a); } long double sin(long double a) { return sinl(a); } long double cos(long double a) { return cosl(a); } long double tan(long double a) { return tanl(a); } long double abs(long double a) { return fabsl(a); } #else #include extern "C" { double pow (double, double); } // Should be #include HIDDEN real __tmp_real; // @doc EXTERNAL real::real () { dzero (ptr ()); } real::real (const real & b) { dcpy (ptr (), b.ptr ()); } real::real (double a) { dftodr (ptr (), a, 9); // Round the number (1.0 is NOT 0.999999999) trail( ); // Delete Trailing zeroes } void real::trail( ) { deltrz (ptr (), ptr () ); // Delete Trailing zeroes } bool real::is_real (const char *s) { bool ok = FALSE; if (s) { while (*s == ' ') s++; // Remove leading spaces before atod ok = atod (__tmp_real.ptr (), (char *) s) != GM_NULL; } return ok; } real::real (const char *s) { if (s) while (*s == ' ') s++; // Remove leading spaces before atod if (s && *s) atod (ptr (), (char *) s); else dzero (ptr ()); } real& real::operator =(const real & b) { dcpy (ptr (), b.ptr ()); return *this; } real& real::operator =(double a) { const real n (a); operator = (n); return *this; } real& real::operator += (const real & b) { dadd (ptr (), ptr (), b.ptr ()); trail( ); return *this; } real& real::operator += (double a) { adddfd (ptr (), ptr (), a); trail( ); return *this; } real& real::operator -= (const real & b) { dsub (ptr (), ptr (), b.ptr ()); trail( ); return *this; } real& real::operator *= (const real & b) { dmul (ptr (), ptr (), b.ptr ()); trail( ); return *this; } real& real::operator /= (const real & b) { const DEC *dst = ddiv (ptr (), ptr (), b.ptr ()); #ifdef DBG if (dst == GM_NULL) { errname (__string, gmec ()); error_box ("Division error: %s", __string); } #endif trail( ); return *this; } bool real::is_zero () const { return diszero (ptr ()); } // @mfunc Ritorna il segno del reale // // @rdesc Ritorna i seguenti valori: // // @flag 0 | Se il numero e' minore di 0 // @flag = 0 | Se il numero e' uguale a 0 // @flag 0 | Se il numero e' maggiore di 0 int real::sign () const { return dsign (ptr ()); } real real::operator - () const { real n; dchgs (n.ptr (), ptr ()); // n.trail( ); return n; } long real::integer () const { return (long)dtodf(ptr ()); } // Certified 91% // @mfunc Trasforma un reale in stringa // // @rdesc Ritorna la stringa nella lunghezza richiesta char *real::string ( int len, // @parm Lunghezza della stringa (compreso decimali) int dec, // @parm Numero di decimali (default UNDEFINED) char pad) const // @parm Carattere di riempimento (default ' ') // @parm char * | picture | Formato della stringa // @syntax string (int len, int dec, char pad); // @syntax string (const char *picture); // // @comm Nel primo caso ritorna una stringa lunga

con

decimali e // inserisce nella stringa stessa il carattere

nel caso la // lunghezza richiesta sia maggiore di quella che risulterebbe per la // completa rappresentazione del reale. // Nel secondo caso ritorna la stringa con il formato stabilito in //

. { __tmp_real = *this; if (dec != UNDEFINED) __tmp_real.round (dec); else __tmp_real.trail(); dtoa (__string, __tmp_real.ptr ()); int lun = strlen (__string); if (lun < len) { const int delta = len - lun; for (int i = lun; i >= 0; i--) __string[i + delta] = __string[i]; for (i = 0; i < delta; i++) __string[i] = pad; } return __string; } // @func ostream& | operator | Permette di reindirizzare il numero // reale per la stampa // // @rdesc Ritorna l'utput sul quale e' stata reindirizzata la stampa ostream & operator << ( ostream & out, // @parm Indica l'output sul quale stampare il numero const real & a) // @parm Numero da stampare { return out << a.string (); } // @func istream& | operator | Permette di leggere un numero reale // // @rdesc Ritorna l'output sul quale e' stato letto il numero istream & operator >> ( istream & in, // @parm Input da cui leggere il numero real & a) // @parm Indirizzo in cui posizionare il numero { in >> __string; atod (a.ptr (), __string); return in; } int real ::precision () { return dprec (ptr ()); } // @mfunc real& | real | round | Arrotonda al numero di decimali passati real & real ::round ( int prec) // @parm Numero di decimali a cui arrotondare il numero (default 0) // @comm Nel caso

sia: // // @flag 0 | Arrotonda al decimale // @flag = 0 | Arrotonda all'intero // @flag 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille) { if (prec < 0) { const double p = ::pow (10.0, -prec); divdfd (ptr (), ptr (), p); dround (ptr (), ptr (), 0); muldfd (ptr (), ptr (), p); } else dround (ptr (), ptr (), prec); return *this; } real & real ::ceil (int prec) { double p = 1.0; if (prec != 0) { p = ::pow (10.0, -prec); divdfd (ptr (), ptr (), p); } DEC integer; dint (&integer, ptr ()); // Extract the integer part if (disgt (ptr (), &integer)) // If positive ... addid (ptr (), &integer, 1); // ... add 1 else dcpy(ptr(), &integer); // If negative if (prec != 0) muldfd (ptr (), ptr (), p); return *this; } real & real ::trunc (int prec) { dtrunc (ptr (), ptr (), prec); return *this; } // @func real | operator + | Somma due numeri reali // // @rdesc Ritorna il valore della somma real operator + ( const real & a, // @parm Primo addendo da sommare const real & b) // @parm Secondo addendo da sommare // @syntax operator +(const real &a, const real &b); // @syntax operator +(double a, const real &b); // @syntax operator +(const real &a, double b); { dadd (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real operator + (double a, const real & b) { __tmp_real = a; return __tmp_real += b; } real operator + (const real & a, double b) { __tmp_real = a; return __tmp_real += b; } // @func real | operator - | Sottrae due numeri reali // // @rdesc Ritorna il valore della sottrazione real operator - ( const real & a, // @parm Primo addendo da sottrarre const real & b) // @parm Secondo addendo da sottrarre // @syntax operator -(const real &a, const real &b); // @syntax operator -(double a, const real &b); // @syntax operator -(const real &a, double b); { dsub (__tmp_real.ptr (), a.ptr (), b.ptr ()); __tmp_real.trail(); return __tmp_real; } real operator - (double a, const real & b) { __tmp_real = a; dsub (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); __tmp_real.trail( ); return __tmp_real; } real operator - (const real & a, double b) { __tmp_real = b; __tmp_real -= a; __tmp_real.trail(); return __tmp_real; } // @func real | operator * | Moltiplica due numeri reali // // @rdesc Ritorna il valore della moltiplicazione real operator *( const real & a, // @parm Primo numero da moltiplicare const real & b) // @parm Secondo numero da moltiplicare // @syntax operator *(const real &a, const real &b); // @syntax operator *(double a, const real &b); // @syntax operator *(const real &a, double b); { dmul (__tmp_real.ptr (), a.ptr (), b.ptr ()); __tmp_real.trail( ); return __tmp_real; } real operator *(double a, const real & b) { muldfd (__tmp_real.ptr (), b.ptr (), a); __tmp_real.trail( ); return __tmp_real; } real operator *(const real & a, double b) { muldfd (__tmp_real.ptr (), a.ptr (), b); __tmp_real.trail( ); return __tmp_real; } // @func real | operator / | Divide due numeri reali // // @rdesc Ritorna il valore della divisione real operator / ( const real & a, // @parm Primo numero da dividere const real & b) // @parm Secondo numero da dividere // @syntax operator /(const real &a, const real &b); // @syntax operator /(double a, const real &b); // @syntax operator /(const real &a, double b); { ddiv (__tmp_real.ptr (), a.ptr (), b.ptr ()); __tmp_real.trail( ); return __tmp_real; } real operator / (double a, const real & b) { __tmp_real = a; ddiv (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); __tmp_real.trail( ); return __tmp_real; } real operator / (const real & a, double b) { __tmp_real = b; ddiv (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ()); __tmp_real.trail( ); return __tmp_real; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator (const real &a, const real &b); // @syntax operator (double a, const real &b); { return disgt (a.ptr (), b.ptr ()); } bool operator > (double a, const real & b) { // dftod(__tmp_real.ptr(), a); // return disgt(__tmp_real.ptr(), b.ptr()); const double n = dtodf (b.ptr ()); return a > n; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator (const real &a, const real &b); // @syntax operator (double a, const real &b); { return dislt (a.ptr (), b.ptr ()); } bool operator < (double a, const real & b) { // dftod(__tmp_real.ptr(), a); // return dislt(__tmp_real.ptr(), b.ptr()); const double n = dtodf (b.ptr ()); return a < n; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator = (const real &a, const real &b); // @syntax operator = (double a, const real &b); { return disge (a.ptr (), b.ptr ()); } bool operator >= (double a, const real & b) { // dftod(__tmp_real.ptr(), a); // return disge(__tmp_real.ptr(), b.ptr()); const double n = dtodf (b.ptr ()); return a >= n; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator = (const real &a, const real &b); // @syntax operator = (double a, const real &b); { return disle (a.ptr (), b.ptr ()); } bool operator <= (double a, const real & b) { // dftod(__tmp_real.ptr(), a); // return disle(__tmp_real.ptr(), b.ptr()); const double n = dtodf (b.ptr ()); return a <= n; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator == (const real &a, const real &b); // @syntax operator == (double a, const real &b); { return diseq (a.ptr (), b.ptr ()); } bool operator == (double a, const real & b) { const double n = dtodf (b.ptr ()); return a == n; } // @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 real & a, // @parm Primo numero da conforntare const real & b) // @parm Secondo numero da confrontare // @syntax operator != (const real &a, const real &b); // @syntax operator != (double a, const real &b); { return !diseq (a.ptr (), b.ptr ()); } bool operator != (double a, const real & b) { const double n = dtodf (b.ptr ()); return a != n; } // @func real | operator % | Ritorna il modulo di due numeri // // @rdesc Ritorna il resto della divisione tra due numeri real operator % ( const real& a, // @parm Primo membro della divisione const real& b) // @parm Secondo membro della divisione { const long l = b.integer(); dmodl (__tmp_real.ptr (), a.ptr (), l); return __tmp_real; } // @func Scambia il numero reale

con il numero real

void swap ( real & a, // @parm Primo numero da scambiare real & b) // @parm Secondo numero da scambiare { SwapDecimal (a.ptr (), b.ptr ()); } // @func Ritorna il numero reale piu' piccolo tra

e

const real& fnc_min ( const real & a, // @parm Primo numero da confrontare const real & b) // @parm Secondo numero da confrontare { dmin (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } // @func Ritorna il numero reale piu' grande tra

e

const real& fnc_max ( const real & a, // @parm Primo numero da confrontare const real & b) // @parm Secondo numero da confrontare { dmax (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } // @func Ritorna la radice quadrata del numero real sqrt ( const real & a) // @parm Numero del quale calcolare la radice { dsqrt (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Ritorna il quadarato del numero real sqr ( const real & a) // @parm Numero del quale calcolare il quadrato { dmul (__tmp_real.ptr (), a.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola 10 a potenza

real exp10 (const real & a) { dalog (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola l'elevamento a potenza

del numero

real pow (const real & a, const real & b) { dpow (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } // @func Calcola e (nepero) elevato ad

real exp (const real & a) { dexp (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola il logaritmo in base 10 del numero real log10 ( const real & a) // @parm Numero del quale calcolare il logaritmo { dlog (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcoa il logaritmo naturale (base e) del numero real log ( const real & a) // @parm Numero del quale calcolare il logaritmo { dln (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola il seno dell'angolo real sin ( const real & a) // @parm Angolo passato in radianti { dsin (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola il coseno dell'angolo real cos ( const real & a) // @parm Angolo passato in radianti { dcos (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Calcola la tangente dell'angolo real tan ( const real & a) // @parm Angolo passato in radianti { dtan (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } // @func Ritorna il valore assoluto di un numero real abs ( const real & a) // @parm Numero del quale si vuole conoscere il valore // assoluto { dabs (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } #endif // Funzioni comuni dei due real TObject* real::dup () const { return new real(*this); } char *real::eng2ita (char *s) { if (s) { char *dot = strchr (s, '.'); if (dot) *dot = ','; } return s; } char *real::ita2eng (const char *s) { int j = 0; if (s) for (int i = 0; s[i]; i++) { switch (s[i]) { case ' ': case '.': break; case ',': __string[j++] = '.'; break; default: __string[j++] = s[i]; break; } } __string[j] = '\0'; return __string; } bool real::is_natural (const char *s) { bool ok = s && *s != '\0'; if (ok) { while (*s == ' ') s++; // Remove leading spaces before if (*s) { while (isdigit(*s)) s++; ok = *s == '\0'; } else ok = FALSE; } return ok; } // Certified 75% char *real ::literals () const { const char *primi20[] = {"", "uno", "due", "tre", "quattro", "cinque", "sei", "sette", "otto", "nove", "dieci", "undici", "dodici", "tredici", "quattordici", "quindici", "sedici", "diciassette", "diciotto", "diciannove"}; const char *decine[] = {"zero", "dieci", "venti", "trenta", "quaranta", "cinquanta", "sessanta", "settanta", "ottanta", "novanta", "cento"}; const char *uni[] = {"uno", "mille", "unmilione", "unmiliardo"}; const char *potenze[] = {"", "mila", "milioni", "miliardi"}; real tmp_real = *this; tmp_real.round(); TString r (tmp_real.string (0, 0)); const bool negativo = r[0] == '-'; if (negativo) r.ltrim (1); TFixed_string risultato (__string, 128); risultato.cut (0); TString centinaia; for (int migliaia = 0;; migliaia++) { int v = r.len () - 3; if (v < -2) break; if (v < 0) v = 0; const int val = atoi (&r[v]); r.cut (v); // Elimina ultimi 3 caratteri v = val; if (v >= 100) { const int c = v / 100; if (c > 1) centinaia = primi20[c]; else centinaia.cut(0); v -= c * 100; centinaia << "cento"; } else centinaia.cut(0); const int d = v / 10; if (d > 1) { centinaia << decine[d]; v -= d * 10; } if (val > 0) { if (v != 1) { centinaia << primi20[v] << potenze[migliaia]; } else if (val > 1) { if (d > 1) centinaia.cut (centinaia.len() - 1); centinaia << "un" << (migliaia ? potenze[migliaia] : "o"); } else centinaia = uni[migliaia]; } risultato.insert(centinaia, 0); } if (negativo) risultato.insert ("meno", 0); return __string; } // Certified 75% char* real::points (int dec) const { const char *str = stringa (0, dec); const int neg = (*str == '-') ? 1 : 0; TFixed_string n ((char *)str, 24); int i; int dot = n.find (','); if (dot < 0) dot = n.len (); if (dec > 0) { if (n[dot] == '\0') n << ','; const int d = strlen (str + dot + 1); // Decimals already there if (d <= dec) for (i = d; i < dec; i++) n << '0'; else n.cut (dot + dec + 1); } for (i = dot - 3; i > neg; i -= 3) n.insert (".", i); return __string; } HIDDEN int get_picture_decimals (const TString& picture) { int decimali = 0; const int virgola = picture.find (','); if (virgola >= 0) { const int len = picture.len (); for (int i = virgola + 1; i < len; i++) if (strchr ("#@~", picture[i])) decimali++; } return decimali; } char* real::string(const char *picture) const { if (*picture == '\0') return string (); if (*picture == '.') return points (atoi (picture + 1)); if (strcmp (picture, "LETTERE") == 0) return literals (); TString v (string()); TString f (picture); const int voluti = get_picture_decimals (f); const int virgola = v.find ('.'); int decimali = (virgola >= 0) ? v.len () - virgola - 1 : 0; for (; voluti > decimali; decimali++) v << '@'; if (voluti < decimali) v.cut (virgola + voluti + (voluti > 0)); int j = v.len () - 1; for (int i = f.len () - 1; i >= 0 && j >= 0; i--) { char &z = f[i]; if (strchr ("#@^", z)) { char c = v[j--]; if (j >= 0 && v[j] == '.') j--; if (z == '^') c = ' '; else { if (c == '@') c = (z == '@') ? '0' : ' '; else if (c == '-' && f[i+1] == '.') { f[i+1] = '-'; c = ' '; } } z = c; } } for (; i >= 0; i--) switch (f[i]) { case '#': case '^': case '.': f[i] = ' '; break; case '@': f[i] = '0'; break; default: break; } return strcpy (__string, f); } // Certified 99% char *real ::stringa (int len, int dec, char pad) const { string (len, dec, pad); if (dec > 0 || dec == UNDEFINED) eng2ita (__string); return __string; } /////////////////////////////////////////////////////////// // Distrib // Oggetto per dividere un real in varie sue percentuali // in modo che la loro somma dia sempre il real di partenza // ///////////////////////////////////////////////////////// void TDistrib::add(real slice) { if (slice > real (1.0)) slice /= 100.0; CHECK (!_ready, "TDistrib: les jeux sont faits"); _slices.add (slice); } real TDistrib::get () { _ready = TRUE; CHECK (_current < _slices.items(), "TDistrib: too many gets"); real r = _tot * ((real &) _slices[_current++]); r.round (_decs); if (r > _tot - _prog) { r = _tot - _prog; _prog = _tot; } else _prog += r; return r; } // @mfunc Inizializza l'oggetto void TDistrib::init ( const real & r, // @parm Importo da dividere bool zap) // @parm Permette di cancellare le percenutali immesse // (default FALSE) // @comm Se

e' vero cancella tutte le percentuali immesse, altrimenti // cambia solo il totale { _current = 0; _prog = 0; _tot = r; _ready = FALSE; if (zap) _slices.destroy(); } /////////////////////////////////////////////////////////// // Importo /////////////////////////////////////////////////////////// const TImporto& TImporto::add_to(TToken_string& s, int pos) const { const bool dare = sezione() == 'D'; const char* v = valore().string(); s.add(dare ? v : "", pos); s.add(dare ? "" : v, pos+1); return *this; } // Cerified 99% const TImporto& TImporto::operator =(TToken_string& sv) { _valore = real(sv.get(0)); if (_valore.is_zero()) { _valore = real(sv.get()); _sezione = 'A'; } else _sezione = 'D'; return *this; } const TImporto& TImporto::set(char s, const real& v) { if (s <= ' ' && v.is_zero()) // Accetta sezioni nulle per importi nulli s = 'D'; CHECKD(s == 'D' || s == 'A', "Sezione errata per importo: codice ", (int)s); _sezione = s; _valore = v; return *this; } const TImporto& TImporto::operator += (const TImporto& i) { if (_valore.is_zero()) _sezione = i._sezione; if (_sezione == i._sezione) _valore += i._valore; else _valore -= i._valore; return *this; } const TImporto& TImporto::operator -= (const TImporto& i) { if (_valore.is_zero()) _sezione = i._sezione; if (_sezione == i._sezione) _valore -= i._valore; else _valore += i._valore; return *this; } const TImporto& TImporto::swap_section() { _sezione = (_sezione == 'D') ? 'A' : 'D'; return *this; } // Normalizza l'importo al parametro s // Valore Azione // A Forza la sezione Avere // D Forza la sezione Dare // < 0 Forza il segno negativo // >=0 Forza il segno positivo const TImporto& TImporto::normalize(char s) { bool ex = FALSE; switch (s) { case 'A': case 'D': ex = s != _sezione; break; default: if (s < 0) ex = _valore.sign() > 0; else ex = _valore.sign() < 0; break; } if (ex) { _valore = -_valore; swap_section(); } return *this; } int TImporto::compare(const TSortable& s) const { const TImporto& i = (const TImporto&)s; const real d = valore() - i.valore(); int res = d.sign(); if (res == 0 && !is_zero()) res = sezione() != i.sezione(); return res; }