campo-sirio/include/real.cpp
angelo 33e37fad53 Corretto metodo real::literals(). Non funzionava correttamente
per numeri come 100000, 200000, 300000 ecc.


git-svn-id: svn://10.65.10.50/trunk@1672 c028cbd2-c16b-5b4b-a496-9718f37d4682
1995-08-03 14:57:10 +00:00

1079 lines
23 KiB
C++
Executable File

#include <ctype.h>
#include <stdlib.h>
#include <gm.h>
extern "C"
{
double pow (double, double);
} // Should be #include <math.h>
#include <strings.h>
#include <real.h>
HIDDEN real __tmp_real;
HIDDEN char __string[80];
const real ZERO (0.0);
// @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)
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 ());
}
// @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 ());
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 <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
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";
} 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 ();
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);
}
// @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 ();
}
// @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
{
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 <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 (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 ());
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;
}
// @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 ());
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;
}
// @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 ());
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;
}
// @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 ());
}
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 <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 ());
}
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 <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 ());
}
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 <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 ());
}
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 <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 ());
}
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 <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;
}
// @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 long b) // @parm Secondo membro della divisione
{
dmodl (__tmp_real.ptr (), a.ptr (), b);
return __tmp_real;
}
// @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 ());
}
// @func Ritorna il numero reale piu' piccolo tra <p a> e <p b>
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 <p a> e <p b>
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 <p a>
real exp10 (const real & a)
{
dalog (__tmp_real.ptr (), a.ptr ());
return __tmp_real;
}
// @func Calcola l'elevamento a potenza <p b> del numero <p a>
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 <p a>
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;
}
///////////////////////////////////////////////////////////
// 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 <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();
}
///////////////////////////////////////////////////////////
// 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 == ZERO)
{
_valore = real(sv.get());
_sezione = 'A';
}
else
_sezione = 'D';
return *this;
}
const TImporto& TImporto::set(char s, const real& v)
{
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;
}
const TImporto& TImporto::normalize()
{
if (_valore.sign() < 0)
{
_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)
res = sezione() != i.sezione();
return res;
}