Files correlati : omnia0.exe Ricompilazione Demo : [ ] Commento : Prima release Acqua Omnia git-svn-id: svn://10.65.10.50/trunk@11726 c028cbd2-c16b-5b4b-a496-9718f37d4682
1810 lines
38 KiB
C++
Executable File
1810 lines
38 KiB
C++
Executable File
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "real.h"
|
|
|
|
const real ZERO(0.0);
|
|
const real UNO(1.0);
|
|
const real CENTO(100.0);
|
|
|
|
#ifdef __LONGDOUBLE__
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
inline long double _atold(const char* str)
|
|
{
|
|
long double num = 0.0;
|
|
sscanf(str, "%Lf", &num);
|
|
return num;
|
|
}
|
|
|
|
real::real () : _dec(0.0)
|
|
{ }
|
|
|
|
real::real (const real& b) : _dec(b._dec)
|
|
{ }
|
|
|
|
real::real (long double a) : _dec(a)
|
|
{ }
|
|
|
|
void real::set_int64(__int64 b)
|
|
{
|
|
_dec = (long double)b;
|
|
}
|
|
|
|
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)
|
|
{
|
|
CHECK(b != 0.0, "Division by zero");
|
|
_dec /= b;
|
|
return *this;
|
|
}
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Ritorna il segno del reale
|
|
//
|
|
// @rdesc Ritorna i seguenti valori:
|
|
//
|
|
// @flag <lt> 0 | Se il numero e' minore di 0
|
|
// @flag = 0 | Se il numero e' uguale a 0
|
|
// @flag <gt> 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%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Trasforma un reale in stringa
|
|
//
|
|
// @rdesc Ritorna la stringa nella lunghezza richiesta
|
|
const 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 <p len> con <p dec> decimali e
|
|
// inserisce nella stringa stessa il carattere <p pad> nel caso la
|
|
// lunghezza richiesta sia maggiore di quella che risulterebbe per la
|
|
// completa rappresentazione del reale.
|
|
// <nl>Nel secondo caso ritorna la stringa con il formato stabilito in
|
|
// <p picture>.
|
|
|
|
{
|
|
TString16 fmt("%");
|
|
if (pad != ' ') fmt << '0';
|
|
if (len != 0) fmt << len;
|
|
if (dec != UNDEFINED) fmt << '.' << dec;
|
|
fmt << "Lf";
|
|
|
|
TString& tmp = get_tmp_string();
|
|
char* __string = tmp.get_buffer(len);
|
|
|
|
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 void ipow10(int pow, double& m, double& d)
|
|
{
|
|
m = d = 1.0;
|
|
if (pow > 0)
|
|
{
|
|
for (int i = pow; i > 0; i--)
|
|
{
|
|
m *= 10.0;
|
|
d *= 0.1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = pow; i < 0; i++)
|
|
{
|
|
m *= 0.1;
|
|
d *= 10.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
int real::precision() const
|
|
{
|
|
const TFixed_string s(string());
|
|
const int d = s.find('.');
|
|
const int p = d < 0 ? 0 : (s.len()-d-1);
|
|
return p;
|
|
}
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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 <p prec> sia:
|
|
//
|
|
// @flag <gt> 0 | Arrotonda al decimale
|
|
// @flag = 0 | Arrotonda all'intero
|
|
// @flag <lt> 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille)
|
|
{
|
|
if (abs(prec) < 20)
|
|
{
|
|
double m, d;
|
|
if (prec != 0)
|
|
{
|
|
ipow10(prec, m, d);
|
|
if (prec < 0)
|
|
_dec /= d;
|
|
else
|
|
_dec *= m;
|
|
}
|
|
|
|
if (_dec >= 0.0)
|
|
_dec = floorl(_dec + 0.5);
|
|
else
|
|
_dec = ceill(_dec - 0.5);
|
|
|
|
if (prec != 0)
|
|
{
|
|
if (prec < 0)
|
|
_dec *= d;
|
|
else
|
|
_dec /= m;
|
|
}
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
real& real::ceil (int prec)
|
|
{
|
|
double m, d;
|
|
if (prec != 0)
|
|
{
|
|
ipow10(prec, m, d);
|
|
_dec *= m;
|
|
}
|
|
_dec = ceill(_dec);
|
|
if (prec != 0)
|
|
// _dec *= d; Risulta stranamente molto impreciso!
|
|
_dec /= m;
|
|
|
|
return *this;
|
|
}
|
|
|
|
real& real::floor (int prec)
|
|
{
|
|
double m, d;
|
|
if (prec != 0)
|
|
{
|
|
ipow10(prec, m, d);
|
|
_dec *= m;
|
|
}
|
|
_dec = floorl(_dec);
|
|
if (prec != 0)
|
|
// _dec *= d; Risulta stranamente molto impreciso!
|
|
_dec /= m;
|
|
|
|
return *this;
|
|
}
|
|
|
|
real& real::trunc(int prec)
|
|
{
|
|
double m, d;
|
|
if (prec != 0)
|
|
{
|
|
ipow10(prec, m, d);
|
|
_dec *= m;
|
|
}
|
|
_dec = floorl(_dec);
|
|
if (prec != 0)
|
|
// _dec *= d; Risulta stranamente molto impreciso!
|
|
_dec /= m;
|
|
return *this;
|
|
}
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Scambia il numero reale <p a> con il numero real <p b>
|
|
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 <gm.h>
|
|
|
|
extern "C"
|
|
{
|
|
double pow (double, double);
|
|
} // Should be #include <math.h>
|
|
|
|
|
|
HIDDEN real __tmp_real;
|
|
|
|
real::real ()
|
|
{
|
|
dzero (ptr ());
|
|
trail();
|
|
}
|
|
|
|
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::set_int64(__int64 b)
|
|
{
|
|
TString80 s; s.format("%I64d", b);
|
|
|
|
atod (ptr (), (char *) (const char *) s);
|
|
trail();
|
|
}
|
|
|
|
void real::trail( )
|
|
{
|
|
deltrz (ptr (), ptr () ); // Delete Trailing zeroes
|
|
}
|
|
|
|
bool real::is_real (const char *s)
|
|
{
|
|
bool ok = TRUE;
|
|
if (s)
|
|
{
|
|
while (*s == ' ')
|
|
s++; // Remove leading spaces before atod
|
|
if (*s)
|
|
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 ());
|
|
|
|
trail();
|
|
}
|
|
|
|
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)
|
|
{
|
|
char * s = get_tmp_string().get_buffer(256);
|
|
errname (s, gmec ());
|
|
error_box ("Division error: %s", s);
|
|
|
|
}
|
|
#endif
|
|
trail( );
|
|
return *this;
|
|
}
|
|
|
|
bool real::is_zero () const
|
|
{
|
|
return diszero (ptr ()) != 0;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Ritorna il segno del reale
|
|
//
|
|
// @rdesc Ritorna i seguenti valori:
|
|
//
|
|
// @flag <lt> 0 | Se il numero e' minore di 0
|
|
// @flag = 0 | Se il numero e' uguale a 0
|
|
// @flag <gt> 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%
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Trasforma un reale in stringa
|
|
//
|
|
// @rdesc Ritorna la stringa nella lunghezza richiesta
|
|
const 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 <p len> con <p dec> decimali e
|
|
// inserisce nella stringa stessa il carattere <p pad> nel caso la
|
|
// lunghezza richiesta sia maggiore di quella che risulterebbe per la
|
|
// completa rappresentazione del reale.
|
|
// <nl>Nel secondo caso ritorna la stringa con il formato stabilito in
|
|
// <p picture>.
|
|
|
|
{
|
|
__tmp_real = *this;
|
|
if (dec != UNDEFINED)
|
|
__tmp_real.round (dec);
|
|
else
|
|
__tmp_real.trail();
|
|
|
|
char * s = get_tmp_string().get_buffer(80);
|
|
dtoa (s, __tmp_real.ptr ());
|
|
int lun = strlen (s);
|
|
|
|
|
|
if (lun < len)
|
|
{
|
|
const int delta = len - lun;
|
|
for (int i = lun; i >= 0; i--)
|
|
s[i + delta] = s[i];
|
|
for (i = 0; i < delta; i++)
|
|
s[i] = pad;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func ostream& | operator <lt><lt> | 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 ();
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func istream& | operator <gt><gt> | 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
|
|
|
|
{
|
|
TString80 s;
|
|
in >> s;
|
|
atod (a.ptr (), s.get_buffer());
|
|
|
|
a.trail();
|
|
return in;
|
|
}
|
|
|
|
|
|
int real::precision() const
|
|
{
|
|
return dprec(ptr());
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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 <p prec> sia:
|
|
//
|
|
// @flag <gt> 0 | Arrotonda al decimale
|
|
// @flag = 0 | Arrotonda all'intero
|
|
// @flag <lt> 0 | Arrotonda al valore passato (es. -3 arrotonda alle mille)
|
|
{
|
|
if (abs(prec < 20))
|
|
{
|
|
if (prec < 0)
|
|
{
|
|
const double p = ::pow (10.0, -prec);
|
|
divdfd (ptr (), ptr (), p);
|
|
dround (ptr (), ptr (), 0);
|
|
muldfd (ptr (), ptr (), p);
|
|
trail();
|
|
}
|
|
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);
|
|
|
|
trail();
|
|
return *this;
|
|
}
|
|
|
|
real & real ::floor (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 (dislt (ptr (), &integer)) // If negative ...
|
|
addid (ptr (), &integer, -1); // ... subtract 1
|
|
else
|
|
dcpy(ptr(), &integer); // If positive
|
|
|
|
if (prec != 0)
|
|
muldfd (ptr (), ptr (), p);
|
|
|
|
trail();
|
|
return *this;
|
|
}
|
|
|
|
real & real ::trunc (int prec)
|
|
{
|
|
dtrunc (ptr (), ptr (), prec);
|
|
return *this;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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)
|
|
{
|
|
__tmp_real = a;
|
|
dmul(__tmp_real.ptr (), __tmp_real.ptr (), b.ptr ());
|
|
__tmp_real.trail( );
|
|
return __tmp_real;
|
|
}
|
|
|
|
real operator *(const real & a, double b)
|
|
{
|
|
__tmp_real = b;
|
|
dmul (__tmp_real.ptr (), a.ptr (), __tmp_real.ptr ());
|
|
__tmp_real.trail( );
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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;
|
|
}
|
|
|
|
// @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 real & a, // @parm Primo numero da conforntare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
|
|
// @syntax operator <gt> (const real &a, const real &b);
|
|
// @syntax operator <gt> (double a, const real &b);
|
|
{
|
|
return disgt (a.ptr (), b.ptr ()) != 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// @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 real & a, // @parm Primo numero da conforntare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
|
|
// @syntax operator <lt> (const real &a, const real &b);
|
|
// @syntax operator <lt> (double a, const real &b);
|
|
|
|
{
|
|
return dislt (a.ptr (), b.ptr ()) != 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// @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 real & a, // @parm Primo numero da conforntare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
|
|
// @syntax operator <gt>= (const real &a, const real &b);
|
|
// @syntax operator <gt>= (double a, const real &b);
|
|
|
|
{
|
|
return disge (a.ptr (), b.ptr ()) != 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// @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 real & a, // @parm Primo numero da conforntare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
|
|
// @syntax operator <lt>= (const real &a, const real &b);
|
|
// @syntax operator <lt>= (double a, const real &b);
|
|
{
|
|
return disle (a.ptr (), b.ptr ()) != 0;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
// @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 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 ()) != 0;
|
|
}
|
|
|
|
bool operator == (double a, const real & b)
|
|
{
|
|
const double n = dtodf (b.ptr ());
|
|
return a == n;
|
|
}
|
|
|
|
// @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 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;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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
|
|
|
|
// @syntax long double operator%(const real& a, const real& b)
|
|
// @syntax real operator % (const real& a, const real& b)
|
|
|
|
{
|
|
const long l = b.integer();
|
|
dmodl (__tmp_real.ptr (), a.ptr (), l);
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Scambia il numero reale <p a> con il numero real <p b>
|
|
void swap (
|
|
real & a, // @parm Primo numero da scambiare
|
|
real & b) // @parm Secondo numero da scambiare
|
|
|
|
{
|
|
SwapDecimal (a.ptr (), b.ptr ());
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Ritorna il numero reale piu' piccolo tra <p a> e <p b>
|
|
const real& fnc_min (
|
|
const real & a, // @parm Primo numero da confrontare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
// @parm long double | a | Primo numero da confrontare
|
|
// @parm long double | b | Secondo numero da confrontare
|
|
|
|
// @syntax const real& fnc_min (const real & a, const real & b)
|
|
// @syntax inline long double fnc_min(long double a, long double b)
|
|
|
|
|
|
{
|
|
dmin (__tmp_real.ptr (), a.ptr (), b.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Ritorna il numero reale piu' grande tra <p a> e <p b>
|
|
const real& fnc_max (
|
|
const real & a, // @parm Primo numero da confrontare
|
|
const real & b) // @parm Secondo numero da confrontare
|
|
// @parm long double | a | Primo numero da confrontare
|
|
// @parm long double | b | Secondo numero da confrontare
|
|
|
|
// @syntax const real& fnc_max (const real & a, const real & b)
|
|
// @syntax inline long double fnc_max(long double a, long double b)
|
|
|
|
{
|
|
dmax (__tmp_real.ptr (), a.ptr (), b.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Ritorna la radice quadrata del numero
|
|
real sqrt (
|
|
const real & a) // @parm Numero del quale calcolare la radice
|
|
// @parm long double | a | Numero del quale calcolare la radice
|
|
|
|
// @syntax real sqrt (const real)
|
|
// @syntax long double sqrt(long double)
|
|
|
|
{
|
|
dsqrt (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Ritorna il quadarato del numero
|
|
real sqr (
|
|
const real & a) // @parm Numero del quale calcolare il quadrato
|
|
// @parm long double | a | Numero del quale calcolare il quadrato
|
|
|
|
// @syntax real sqr (const real)
|
|
// @syntax long double sqr(long double)
|
|
|
|
{
|
|
dmul (__tmp_real.ptr (), a.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola 10 a potenza <p a>
|
|
real exp10 (
|
|
const real & a) // @parm Esponente al quale elevare
|
|
// @parm long double | a | Esponente al quale elevare
|
|
|
|
// @syntax real exp10 (const real)
|
|
// @syntax long double exp10 (long double)
|
|
|
|
|
|
{
|
|
dalog (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola l'elevamento a potenza <p b> del numero <p a>
|
|
real pow (
|
|
const real & a, // @parm Numero da elevare a potenza
|
|
const real & b) // @parm Esponente
|
|
// @parm long double | a | Numero da elevare a potenza
|
|
// @parm long double | b | Esponente
|
|
|
|
// @syntax real pow (const real & a, const real & b)
|
|
// @syntax long double pow(long double a, long double b)
|
|
|
|
{
|
|
dpow (__tmp_real.ptr (), a.ptr (), b.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola e (nepero) elevato ad <p a>
|
|
real exp (
|
|
const real & a) // @parm Esponente
|
|
// @parm long double | a | Esponente
|
|
|
|
// @syntax real exp (const real & a)
|
|
// @syntax long double exp(long double a)
|
|
|
|
{
|
|
dexp (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola il logaritmo in base 10 del numero
|
|
real log10 (
|
|
const real & a) // @parm Numero del quale calcolare il logaritmo
|
|
// @parm long double | a | Numero del quale calcolare il logaritmo
|
|
|
|
// @syntax real log10 (const real & a)
|
|
// @syntax long double log10(long double a)
|
|
|
|
{
|
|
dlog (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcoa il logaritmo naturale (base e) del numero
|
|
real log (
|
|
const real & a) // @parm Numero del quale calcolare il logaritmo
|
|
// @parm long double | a | Numero del quale calcolare il logaritmo
|
|
|
|
// @syntax real log (const real & a)
|
|
// @syntax long double log(long double a)
|
|
|
|
{
|
|
dln (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola il seno dell'angolo
|
|
real sin (
|
|
const real & a) // @parm Angolo passato in radianti
|
|
// @parm long double | a | Angolo passato in radianti
|
|
|
|
// @syntax real sin (const real & a)
|
|
// @syntax long double sin (long double a)
|
|
|
|
{
|
|
dsin (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola il coseno dell'angolo
|
|
real cos (
|
|
const real & a) // @parm Angolo passato in radianti
|
|
// @parm long double | a | Angolo passato in radianti
|
|
|
|
// @syntax real cos (const real & a)
|
|
// @syntax long double cos (long double a)
|
|
|
|
|
|
{
|
|
dcos (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Calcola la tangente dell'angolo
|
|
real tan (
|
|
const real & a) // @parm Angolo passato in radianti
|
|
// @parm long double | a | Angolo passato in radianti
|
|
|
|
// @syntax real tan (const real & a)
|
|
// @syntax long double tan (long double a)
|
|
|
|
|
|
{
|
|
dtan (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @func Ritorna il valore assoluto di un numero
|
|
real abs (
|
|
const real & a) // @parm Numero del quale si vuole conoscere il valore assoluto
|
|
// @parm long double | a | Numero del quale si vuole conoscere il valore assoluto
|
|
|
|
// @syntax real abs (const real & a)
|
|
// @syntax long double abs(long double a)
|
|
|
|
{
|
|
dabs (__tmp_real.ptr (), a.ptr ());
|
|
return __tmp_real;
|
|
}
|
|
|
|
#endif
|
|
|
|
// Funzioni comuni dei due real
|
|
|
|
TObject* real::dup () const
|
|
{
|
|
return new real(*this);
|
|
}
|
|
|
|
const char *real::eng2ita (char *s)
|
|
{
|
|
if (s)
|
|
{
|
|
char *dot = strchr (s, '.');
|
|
if (dot)
|
|
*dot = ',';
|
|
}
|
|
return s;
|
|
}
|
|
|
|
// Elimina gli spazi ed i punti, converte le virgole in punti
|
|
const char *real::ita2eng (const char *s)
|
|
{
|
|
TString& tmp = get_tmp_string();
|
|
char* __string = tmp.get_buffer(strlen(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_null(const char *s)
|
|
{
|
|
bool z = TRUE;
|
|
if (s != NULL) for (const char* n = s; *n; n++)
|
|
{
|
|
if (strchr("123456789", *n) != NULL)
|
|
{
|
|
z = FALSE;
|
|
break;
|
|
}
|
|
if (strchr(" ,-.0", *n) == NULL)
|
|
break;
|
|
}
|
|
return z;
|
|
}
|
|
|
|
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%
|
|
const 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.trunc();
|
|
|
|
TString r (tmp_real.string (0, 0));
|
|
const bool negativo = r[0] == '-';
|
|
if (negativo)
|
|
r.ltrim (1);
|
|
|
|
TString& risultato = get_tmp_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)
|
|
{
|
|
if (d == 8 && centinaia.right(1)[0] == 'o')
|
|
centinaia.rtrim(1);
|
|
centinaia << decine[d];
|
|
v -= d * 10;
|
|
}
|
|
|
|
if (val > 0)
|
|
{
|
|
if (v != 1)
|
|
{
|
|
if (v == 8)
|
|
centinaia.rtrim(1);
|
|
centinaia << primi20[v] << potenze[migliaia];
|
|
}
|
|
else if (val > 1)
|
|
{
|
|
if (d > 1)
|
|
centinaia.rtrim(1);
|
|
centinaia << "un" << (migliaia ? potenze[migliaia] : "o");
|
|
}
|
|
else
|
|
centinaia = uni[migliaia];
|
|
}
|
|
|
|
risultato.insert(centinaia, 0);
|
|
}
|
|
|
|
if (tmp_real != *this) // Ci sono dei decimali!
|
|
{
|
|
TString80 res = risultato;
|
|
const real tmp_dec = abs(*this - tmp_real);
|
|
TString80 str = tmp_dec.string();
|
|
str.ltrim(2); str.cut(3);
|
|
res << '/' << str;
|
|
risultato = res;
|
|
}
|
|
|
|
if (negativo)
|
|
risultato.insert ("meno", 0);
|
|
return risultato;
|
|
}
|
|
|
|
// Certified 75%
|
|
const char* real::points (int dec) const
|
|
{
|
|
const char *str = stringa (0, dec);
|
|
const int neg = (*str == '-') ? 1 : 0;
|
|
TFixed_string n ((char *)str, 64);
|
|
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 str;
|
|
}
|
|
|
|
HIDDEN int get_picture_decimals (const TString& picture, char& decsep)
|
|
{
|
|
int decimali = 0;
|
|
int virgola = -1;
|
|
|
|
if (decsep == ',')
|
|
{
|
|
int firstcomma = -1, lastcomma = -1, firstdot = -1, lastdot = -1;
|
|
for (int i = 0; picture[i]; i++)
|
|
{
|
|
if (picture[i] == ',')
|
|
{
|
|
if (firstcomma < 0) firstcomma = i;
|
|
lastcomma = i;
|
|
}
|
|
else if (picture[i] == '.')
|
|
{
|
|
if (firstdot < 0) firstdot = i;
|
|
lastdot = i;
|
|
}
|
|
}
|
|
if (lastcomma >= 0 && lastdot >= 0)
|
|
{
|
|
virgola = lastcomma > lastdot ? lastcomma : lastdot;
|
|
decsep = picture[virgola];
|
|
}
|
|
else
|
|
if (lastcomma >= 0) virgola = lastcomma;
|
|
}
|
|
else 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;
|
|
}
|
|
|
|
const char* real::string(const char *picture) const
|
|
{
|
|
if (*picture == '\0')
|
|
return string ();
|
|
if (*picture == '.')
|
|
return points (atoi (picture + 1));
|
|
if (stricmp (picture, "LETTERE") == 0)
|
|
return literals ();
|
|
|
|
TString v (string());
|
|
TString& f = get_tmp_string();
|
|
f = picture;
|
|
|
|
char decsep = ','; // Separatore dei decimali
|
|
if (f[f.len() - 1] == 'E')
|
|
{
|
|
f.rtrim(1);
|
|
decsep = '.';
|
|
}
|
|
|
|
// Calcola il numero di decimali voluti ed eventualmente
|
|
// determina il vero separatore dei decimali
|
|
const int voluti = get_picture_decimals (f, decsep);
|
|
const char migsep = decsep == '.' ? ',' : '.'; // Separatore delle migliaia
|
|
|
|
const int virgola = v.find ('.'); // v e' la nostra cifra, certamente in english format
|
|
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;
|
|
bool sign(FALSE);
|
|
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 == '-')
|
|
{
|
|
if (z == '@') // Altrimenti -10 con picture @@@@@ diventa "00-10"
|
|
{
|
|
if (f[i+1] == migsep)
|
|
f[i+1] = '0';
|
|
sign=TRUE; // posticipa l'append del segno
|
|
i++;
|
|
c=z;
|
|
} else {
|
|
if (f[i+1] == migsep ) // Altrimenti -100 diventa -.100
|
|
{
|
|
f[i+1] = '-';
|
|
c = ' '; //OK
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
z = c;
|
|
}
|
|
}
|
|
for (int i2=0; i2 <= i; i2++)
|
|
if (f[i2] == '@')
|
|
{
|
|
if (sign)
|
|
{
|
|
f[i2] = '-'; // add sign in first pos
|
|
sign=FALSE;
|
|
}
|
|
else
|
|
f[i2] = '0';
|
|
}
|
|
for (; i >=0 ; i--)
|
|
switch (f[i])
|
|
{
|
|
case '#':
|
|
case '^':
|
|
case '.':
|
|
case ',':
|
|
f[i] = ' ';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
return f;
|
|
}
|
|
|
|
// Certified 99%
|
|
const char* real::stringa (int len, int dec, char pad) const
|
|
{
|
|
char* str = (char*)string(len, dec, pad);
|
|
if (dec > 0 || dec == UNDEFINED)
|
|
eng2ita (str);
|
|
return str;
|
|
}
|
|
|
|
void real::print_on(ostream& out) const
|
|
{
|
|
out << 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;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @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 <p zap> e' vero cancella tutte le percentuali immesse, altrimenti
|
|
// cambia solo il totale
|
|
{
|
|
_current = 0; _prog = 0;
|
|
_tot = r; _ready = FALSE;
|
|
if (zap) _slices.destroy();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// Generic_distrib
|
|
// Oggetto per dividere un real in parti prefissate
|
|
// in modo che la loro somma dia sempre il real di partenza
|
|
// /////////////////////////////////////////////////////////
|
|
|
|
|
|
void TGeneric_distrib::add(real slice)
|
|
{
|
|
CHECK (!_ready, "TGeneric_distrib: les jeux sont faits");
|
|
_totslices += slice;
|
|
_slices.add (slice);
|
|
}
|
|
|
|
real TGeneric_distrib::get ()
|
|
{
|
|
_ready = TRUE;
|
|
CHECK (_current < _slices.items(), "TGeneric_distrib: too many gets");
|
|
real & currslice = (real &) _slices[_current++];
|
|
real r = currslice;
|
|
if (_tot != _totslices)
|
|
{
|
|
if (_tot < 1E9 && currslice < 1E9)
|
|
r = (_tot * currslice) / _totslices;
|
|
else
|
|
r *= (_tot / _totslices);
|
|
}
|
|
r.round (_decs);
|
|
_tot -= r;
|
|
_totslices -= currslice;
|
|
return r;
|
|
}
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Inizializza l'oggetto
|
|
void TGeneric_distrib::init (
|
|
const real & r, // @parm Importo da dividere
|
|
bool zap) // @parm Permette di cancellare le percenutali immesse
|
|
// (default FALSE)
|
|
|
|
// @comm Se <p zap> e' vero cancella tutte le percentuali immesse, altrimenti
|
|
// cambia solo il totale
|
|
{
|
|
_current = 0; _totslices = 0;
|
|
_tot = r; _ready = FALSE;
|
|
if (zap) _slices.destroy();
|
|
else
|
|
{
|
|
const int items = _slices.items();
|
|
for (int i = 0; i < items; i++)
|
|
_totslices += (real &) _slices[i];
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////
|
|
// 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;
|
|
}
|
|
|
|
|
|
// @doc EXTERNAL
|
|
|
|
// @mfunc Normalizza il segno o la sezione in base al parametro s
|
|
const TImporto& TImporto::normalize(
|
|
char s) // @parm Tipo di normalizzazione da effettuare:
|
|
//
|
|
// @flag A | Forza la sezione Avere
|
|
// @flag D | Forza la sezione Dare
|
|
// @flag <gt>0 | Forza il segno negativo
|
|
// @flag <lt>=0 | Forza il segno positivo
|
|
|
|
{
|
|
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 v = i.sezione() == sezione() ? i.valore() : -i.valore();
|
|
const real d = valore() - v;
|
|
const int res = d.sign();
|
|
return res;
|
|
}
|
|
|
|
bool TImporto::is_zero() const
|
|
{
|
|
#ifdef __LONGDOUBLE__
|
|
return fabsl(_valore) < 0.00001;
|
|
#else
|
|
return _valore.is_zero();
|
|
#endif
|
|
} |