Newsgroup: it.comp.lang.c++
Titolo: Stampa di un numero complesso

Voglio mandare su cout un numero complesso nella forma rettangolare
z=a+jb
Es.
3+j2, me lo deve stampare (3,2j)
3+j0, me lo deve stampare (3)
0-j4, me lo deve stampare (-4j)
Ho provato con l'overloading dell'operatore di estrazione dallo stream, 
attraverso una funzione friend, ma non funziona:
/////////////////////////////////////////////////////
ostream& operator<< (ostream& out, Complex z)
{
    out << ( z.isImag() ? "" : z.Re )
        << ( z.isReal() ? "" : (", " << z.Im << "j") );
}
/////////////////////////////////////////////////////
Le funzioni predicative isImag() e isReal() restituiscono 1 se il numero 
complesso è, rispettivamente, immaginario puro o reale puro:
bool isReal() const { return (Im==0); };
bool isImag() const { return (Re==0); };
L'errore di compilazione che ottengo è:
In function `std::ostream& operator<<(std::ostream&, Complex)':
have different types
invalid operands of types `const char[3]' and `float' to binary 
`operator<<'
Spero di non dover ricorrere alla printf... ;-)
Grazie e ciao.

 Voglio mandare su cout un numero complesso nella forma rettangolare
Non ti incartare con l'operatore ternario e procedi linearmente (e
ricordati di restituire lo stream):
class Complex {
public:
  Complex(int re, int im): _re(re), _im(im) { };
  friend std::ostream& operator<<(std::ostream& os, Complex z);
private:
  int _re, _im;
};
std::ostream& operator<<(std::ostream& os, Complex z) {
    os << "(";
    if (z._re != 0)
      os << z._re;
    if (z._im != 0) {
       if (z._re != 0)
         os << ", ";
       os << z._im << "j";
    }
    os << ")";
    return os;
}
int main()
{
    Complex a(0, 2);
    Complex b(3, 0);
    Complex c(1, 2);
    std::cout << a << std::endl;
    std::cout << b << std::endl;
    std::cout << c << std::endl;
    return 0;
}

 Spero di non dover ricorrere alla printf... ;-)
Se fai certi errori non c'e' printf che tenga ;-)
Ciao,
Nicola

 dello stesso tipo.
Ho capito allora dove è il problema.

 }
L'ho implementata diversamente, ma sostanzialmente ho fatto la stessa cosa.
Mi conforta sapere che non c'avevo scelte.
Grazie

 L'ho implementata diversamente, ma sostanzialmente ho fatto la stessa cosa.
Non direi: il tuo codice non compila, il mio sì e funziona.

     if (z._im != 0) {
Occhio solo che se _re e _im anzichč int sono in virgola mobile, il 
confronto "esatto" con 0 potrebbe essere non appropriato. (specialmente 
se il numero che vuoi stampare viene fuori da calcoli floating-point per 
via dei vari errori di "calcolo numerico" che si possono verificare)
Spesso si preferisce usare una roba tipo:
...
if( abs(z._re) > EPSILON )
...
dove EPSILON č una costante piccola
GM

 Occhio solo che se _re e _im anzichè int sono in virgola mobile
Sarebbe infatti un altro discorso. Visti gli errori di arrotondamento
impliciti nel formato finito dei fp e quindi l'impossibilità di
arrivare allo 0 se non come approssimazioni successive, sarebbe
necessario accertarsi di essere in un intervallo sufficientemente
piccolo intorno al valore limite. Avrei però complicato un codice
d'esempio.

        << ( z.isReal() ? "" : (", " << z.Im << "j") );
                                 ^^^^^^^^^^^^
Il tuo problema è che hai usato un operator>> per char[3], vale a dire
", ", invece che ostream. Per come hai messo le parentesi, il programma
dovrebbe cercare di applicare operator>> a ", " e z.Im, ma questa
funzione non esiste (e meno male).
Io procederei (più leggibilmente, secondo me) così:
ostream& operator<< (ostream& out, Complex z)
{
	if( z.isReal() )
		out << z.Re;
	else if( z.isImag() )
		out << z.Im << "j";
	else
		out << z.Re << "," << z.Im << "j";
	return out;
}
L'operatore ternario non è malvagio in sé, ma usarlo quando non ci sono
esattamente due casi (ne hai tre) diventa facilmente controproducente.
Ciao,
- -Federico
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (GNU/Linux)
Comment: Using GnuPG with SUSE - 
http://enigmail.mozdev.org
iD8DBQFIcyQQBIpu+y7DlLcRAgjHAJ4kejJNs9JdglQe5II+SU+Sy92hnACgnxPE
oz3X7EszuifhzyvZ5MbpcUM=
=WFLf
-----END PGP SIGNATURE-----

 
abs? ma non sarebbe fabs?

 Non direi: il tuo codice non compila, il mio sě e funziona.
Mi riferivo a una seconda versione in cui avevo recepito il consiglio di 
non usare l'operatore ternario

GuGu ha scritto:

fabs è in C (ancora supportato per compatibilità ma "sconsigliato")
abs è in C++.
GM


Uso VS6.0, dipendera' da quello forse? Perche' anche nell'help mi segnala 
tranquillamente fabs/abs. 

GuGu ha scritto:

La documentazione è carente, E vs6 è molto lontano dallo standard.
in questo caso ti conviene usare fabs

 in questo caso ti conviene usare fabs
Ma infatti adesso stavo vagliando di migrare definitivamente a VS2005 o 
VS2008, su un altro NG chiedo infatti lumi in merito.