#include #include #include extern "C" { double pow (double, double); } // Should be #include #include #include HIDDEN real __tmp_real; HIDDEN char __string[80]; const real ZERO (0.0); 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) deltrz (ptr (), ptr ()); // Delete Trailing zeroes } 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_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; } 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; } 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 ()); return *this; } real & real::operator += (double a) { adddfd (ptr (), ptr (), a); return *this; } real & real::operator -= (const real & b) { dsub (ptr (), ptr (), b.ptr ()); return *this; } real & real::operator *= (const real & b) { dmul (ptr (), ptr (), b.ptr ()); 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 return *this; } TObject *real:: dup () const { return new real (*this); } bool real::is_zero () const { return diszero (ptr ()); } int real::sign () const { return dsign (ptr ()); } real real::operator - () const { real n; dchgs (n.ptr (), ptr ()); return n; } long real::integer () const { return (long)dtodf(ptr ()); } // Certified 91% char *real::string (int len, int dec, char pad) const { __tmp_real = *this; if (dec != UNDEFINED) __tmp_real.round (dec); else deltrz (__tmp_real.ptr (), __tmp_real.ptr ()); 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; } // 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; } // 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"}; __tmp_real = *this; __tmp_real.round (0); TString80 r (__tmp_real.string (0, 0)); const bool negativo = r[0] == '-'; if (negativo) r.ltrim (1); TFixed_string risultato (__string, 80); risultato.cut (0); TString80 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"; } const int d = v / 10; if (d > 1) { centinaia << decine[d]; v -= d * 10; } 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 (); TString80 v (string()); TString80 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); } ostream & operator << (ostream & out, const real & a) { return out << a.string (); } istream & operator >> (istream & in, real & a) { in >> __string; atod (a.ptr (), __string); return in; } int real ::precision () { return dprec (ptr ()); } real & real ::round (int prec) { 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; } real operator + (const real & a, const real & 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; } real operator - (const real & a, const real & b) { dsub (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real operator - (double a, const real & b) { __tmp_real = a; dsub (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); return __tmp_real; } real operator - (const real & a, double b) { __tmp_real = b; return __tmp_real -= a; } real operator *(const real & a, const real & b) { dmul (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real operator *(double a, const real & b) { muldfd (__tmp_real.ptr (), b.ptr (), a); return __tmp_real; } real operator *(const real & a, double b) { muldfd (__tmp_real.ptr (), a.ptr (), b); return __tmp_real; } real operator / (const real & a, const real & b) { ddiv (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real operator / (double a, const real & b) { __tmp_real = a; ddiv (__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ()); return __tmp_real; } real operator / (const real & a, double b) { __tmp_real = b; ddiv (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ()); return __tmp_real; } bool operator > (const real & 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; } bool operator < (const real & 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; } bool operator >= (const real & 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; } bool operator <= (const real & 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; } bool operator == (const real & 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; } bool operator != (const real & 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; } real operator % (const real & a, const long b) { dmodl (__tmp_real.ptr (), a.ptr (), b); return __tmp_real; } void swap (real & a, real & b) { SwapDecimal (a.ptr (), b.ptr ()); } real fnc_min (const real & a, const real & b) { dmin (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real fnc_max (const real & a, const real & b) { dmax (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real sqrt (const real & a) { dsqrt (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real sqr (const real & a) { dmul (__tmp_real.ptr (), a.ptr (), a.ptr ()); return __tmp_real; } real exp10 (const real & a) { dalog (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real pow (const real & a, const real & b) { dpow (__tmp_real.ptr (), a.ptr (), b.ptr ()); return __tmp_real; } real exp (const real & a) { dexp (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real log10 (const real & a) { dlog (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real log (const real & a) { dln (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real sin (const real & a) { dsin (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real cos (const real & a) { dcos (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real tan (const real & a) { dtan (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } real abs (const real & a) { dabs (__tmp_real.ptr (), a.ptr ()); return __tmp_real; } /////////////////////////////////////////////////////////// // 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; } void TDistrib::init (const real & r, bool zap) { _current = 0; _prog = 0; _tot = r; _ready = FALSE; if (zap) _slices.destroy(); }