#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; } 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) { __tmp_real = *this; adddfd(ptr(), __tmp_real.ptr(), a); return *this; } real& real::operator -=(const real& b) { __tmp_real = *this; dsub( ptr(), __tmp_real.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; } int real::integer() const { return dtoi(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()); // if (len == 0) dtoa(__string, __tmp_real.ptr()); /* else { char f[16]; if (dec == UNDEFINED) sprintf(f, "%%%dt", len); else sprintf(f, "%%%d.%dt", len, dec); dsprintf(__string, f, __tmp_real.ptr()); } if (dec <= 0 || dec == UNDEFINED) // Toglie una eventuale parte decimale .00 { if (dot) { for (const char* z = dot + 1; *z; z++) if (*z != '0') break; if (!*z) *dot = '\0'; } } */ int lun = strlen(__string); /* char* dot = strchr(__string, '.'); int d = dot ? strlen(dot+1) : 0; // Decimals already there if (d < dec) { if (dot == NULL) __string[lun++] = '.'); for (;d < dec; d++) __string[lun++] = '0'; __string[lun] = '\0'; } else if (dec >= 0 && d > dec) { *(dot+dec+(dec>0)) = '\0'; 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); TString r(__tmp_real.string(0, 0)); const bool negativo = r[0] == '-'; if (negativo) r.ltrim(1); TFixed_string risultato(__string, 80); risultato.cut(0); TString centinaia(16); 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(); 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 (v[j] == '.') j--; if (z == '~') c = ' '; else if (c == '@') c = (z == '@') ? '0' : ' '; 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) { p = ::pow(10.0, -prec); divdfd(ptr(), ptr(), p); } DEC integer; dint(&integer, ptr()); // Extract the integer part if (disne(ptr(), &integer)) // If different ... addid(ptr(), &integer, 1); // add 1 if (prec) 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) { _current = 0; _prog = 0; _tot = r; _ready = FALSE; }