2
\$\begingroup\$
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;

class Complex {
private:
    double Rez, Imz, ro, fi;

public:
    Complex() {
        Rez = 0.;
        Imz = 0.;
        ro = 0.;
    fi = 0.;
}

Complex(double x, double y) {
    Rez = x;
    Imz = y;
    ro = sqrt(pow(x,2)+pow(y,2));
    fi = atan(y/x);
 }

~Complex() {}

double get_Rez() {return Rez;} 
double get_Imz() {return Imz;} 
double get_ro() {return ro;} 
double get_fi() {return fi;}

void set_Rez(double a) {Rez = a; ro = sqrt(pow(Rez,2)+pow(Imz,2)); fi = acos(Rez/ro);}
void set_Imz(double a) {Imz = a; ro = sqrt(pow(Rez,2)+pow(Imz,2)); fi = acos(Rez/ro);}
void set_ro(double a) {ro = a; Rez = ro*cos(fi); Imz = ro*sin(fi);}
void set_fi(double a) {fi = a; Rez = ro*cos(fi); Imz = ro*sin(fi);}

Complex & inverso() {       
    this->set_Rez(this->get_Rez()/pow(this->get_ro(),2));
    this->set_Imz(-this->get_Imz()/pow(this->get_ro(),2));
    return *this;
}

};

These two are the functions to work with my complex numbers. Is it possible to change them in order to make them accept also doubles as input? In that case, would it be possible to make them give a double as an output? Is it correct to say that my functions haven't got side effects? Would it be better to put the functions in the class as data members?

Complex somma(Complex a, Complex b) {
    Complex c;
    c.set_Rez(a.get_Rez()+b.get_Rez());
    c.set_Imz(a.get_Imz()+b.get_Imz());
    return c;
}

Complex prodotto(Complex a, Complex b) {
    Complex c;
    c.set_ro(a.get_ro()*b.get_ro());
    c.set_fi(a.get_fi()+b.get_fi());
    return c;
}
\$\endgroup\$
  • \$\begingroup\$ (set_ro()/fi look dangerous for zero. Or non-paired use, come think of it.) \$\endgroup\$ – greybeard Mar 15 '18 at 23:32
  • \$\begingroup\$ (Same for Complex(0, y). Does inverso() work? The set_Rez() should change ro "before Imz gets computed".) \$\endgroup\$ – greybeard Mar 15 '18 at 23:38
  • \$\begingroup\$ @greybeard Yeah that's right! I hadn't checked that case! And I have to work on the inverso function... Tomorrow I'll edit everything hopefully \$\endgroup\$ – Gitana Mar 15 '18 at 23:47
  • \$\begingroup\$ what is ro and fi? (PS new C++ Learner still trying to learn, good at maths only insert laugh) \$\endgroup\$ – Gareth Ma Mar 15 '18 at 23:50
  • 2
    \$\begingroup\$ Is there a good reason not to use std::complex<double> here? If you're making your own for a learning exercise, you should add reinventing-the-wheel to your tags. \$\endgroup\$ – Toby Speight Mar 16 '18 at 10:38
5
\$\begingroup\$

A complex number class is very useful! This is pretty straightforward and easy to understand, too.

The Class

First, I should mention that if you haven't already seen it, there is a complex class in the standard template library. It's great to make your own so that you can learn how it works, but just wanted to mention it in case you missed it.

I think having 2 ways of using the data (real and imaginary parts vs. magnitude and angle) is a great idea. However, I would keep only one pair around and have functions to calculate the others. For example, you might keep the real and imaginary parts and calculate the magnitude and angle only when needed. (Or the reverse if you find that it's more common to use the magnitude and angle.) The reason is that one set of the data can get out of sync with the other. The constructor that takes arguments sets the real and imaginary parts, and then calculates the magnitude and angle. The set_* methods also have to recalculate both parts. If you ever expand the class, you'll have to ensure that every method always does the calculations 2 ways - once for real/imaginary parts, and again for magnitude and angle. This is likely to be slow. If you kept only one representation, you could simply do the conversion to the other representation only when asked for data in that format.

The Functions

I'm guessing from the names that the 2 functions calculate the sum and product of 2 Complex numbers? You ask:

Is it possible to change them in order to make them accept also doubles as input?

There are 2 ways you could approach that. You could simply make an overloaded version:

double somma(double a, double b) {
    double c;
    c = a + b;
    return c;
}

Or you could use templates. To do that, you need to have an operator+() for your Complex class. Then you can write somma() as:

template <typename T>
T somma(T a, T b) {
    T c;
    c = a + b;
    return c;
}

The compiler will then change out T for whatever type the arguments are when you call it. If you call it like this:

Complex x(2, 5);
Complex y(3, 6);
Complex z = somma(x, y);

it will do what your function currently does. If x, y, and z are float or double, then it will use float for the type and return the expected result.

Is it correct to say that my functions haven't got side effects?

Yes, it is. They don't set any state that a caller can't see. They don't cause anything to be output other than the return value of the function.

Would it be better to put the functions in the class as data members?

That depends on how you're going to use them. In general, for a class that represents a type of number having operator+() and operator*() (and related ones like operator+=() etc.) is probably a good idea.

\$\endgroup\$
  • \$\begingroup\$ thank you for the answer! Later I'll correct the program with your suggestions \$\endgroup\$ – Gitana Mar 16 '18 at 8:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.