Solved

Understanding complex numbers recursive power in C++

Posted on 2014-12-26
10
117 Views
Last Modified: 2015-01-14
I have written the complex number class, with method of finding power of the complex number using recusrion.
But I have not understand till the end how it work (that sounds weird)
So your aim is to explain why it works.
My idea is that the variable
comp t has different address at each recusive call so it may accumulate all chain of recusrive call correctly.

when I write this
return *this * rec_power(base,  n-1);

Open in new window


instead of this

comp t = *this * rec_power(base, n-1);
return t;

Open in new window


it writes to the same address, the address of this?
Who may explain in detail?


#include <iostream>
#include <fstream>
#include <cmath>
#include <iomanip>

using namespace std;


template <typename T>
class comp
{
public:
    T im;
    T re;

public:
    // Constructor with parameters
    comp(T re, T im)
    {
        this->im = im;
        this->re = re;
    }

    // Default constructor
    comp()
    {
        this->im = 0;
        this->re = 0;
    }

    // Constructor with one param. Assuming that single parameter
    // is the real part of the comple number
    comp(T re)
    {
        this->re = re;
    }

    // Copy constructor
    comp(const comp& c)
    {
        re = c.re;
        im = c.im;
    }

    // Empty destructor
    ~comp() {};

    comp& operator+(comp& second)
    {
        comp result;
        result.re = this->re + second.re;
        result.im = this->im + second.im;
        return result;
    }

    // Multiplying a complex number by another complex number
    comp& operator*(comp& second)
    {
        comp result;
        result.re = this->re * second.re + (-1)* this->im * second.im;
        result.im = this->re * second.im + this->im * second.re;
        return result;
    }

    // Multiplying a complex number by another number number
    comp& operator*(T n)
    {
        comp result;
        result.re = this->re * n;
        result.im = this->im * n;
        return result;
    }
    T modulus()
    {
        return sqrt(this->re*this->re + this->im*this->im);
    }

    comp& it_power(int n)
    {
        comp result(1, 0);
        for (int i = 1; i <= n; i++)
            result = *this * result;

        return result;
    }

    comp& rec_power(comp base, int n)
    {
        comp one(1, 0);
        if (n == 0)
            return one;
        else if (n == 1)
            return *this;
        else
        {
            comp t = *this * rec_power(base, n-1);
            return t;
            // investigate why this does not work
            //return *this * rec_power(base,  n-1);
        }

    }

    // Overloading input operator
    friend std::ostream& operator<<(ostream& out, comp& c)
    {
        out << setprecision(2) << fixed
            << "(" << c.re << ", " << c.im
            << "i)" << endl;
        return out;
    }

    // Overloading output operator
    friend std::istream& operator>>(istream& in, comp& c)
    {
        in >> c.re ;
        in >> c.im;
        return in;
    }


};


int main()
{
    comp<double> myc(3, 2);
    comp<double> myc2(1, 4);
//    cin >> myc;
//    cin >> myc2;

    comp<double> r = myc + myc2;
    comp<double> m = myc * myc;
    cout << r;
    cout << m;

    cout << r.modulus() << endl;
    cout << m.modulus() << endl;
    cout << myc.it_power(6) << endl;
    cout << myc.rec_power(myc, 6) << endl;

    return 0;
}

Open in new window

0
Comment
Question by:Nusrat Nuriyev
  • 4
  • 3
  • 3
10 Comments
 
LVL 19

Expert Comment

by:mrwad99
ID: 40519765
return *this * rec_power(base,  n-1);

Open in new window


This will update the object on which the function is being called (the "this" pointer).

comp t = *this * rec_power(base, n-1);
return t;

Open in new window


This will return a new object, without modifying the object on which the function is being called.

Incidentally, your code has a lot of semantic errors in that you return references to temporary objects; for example,

comp& it_power(int n)
{
        comp result(1, 0);
        for (int i = 1; i <= n; i++)
            result = *this * result;

        return result;
}

Open in new window


You create the variable 'result' on the stack, and return a reference to it.  When it_power() returns, that object will be destroyed hence you will return a reference to rubbish memory.  I suggest you remove all occurrences of such code.
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 40519767
Incidentally, generally speaking it is best to avoid recursion where possible by using for loops or similar, like you do in your it_power() method.
0
 

Author Comment

by:Nusrat Nuriyev
ID: 40519832
Could you provide any arguments?
0
 

Author Comment

by:Nusrat Nuriyev
ID: 40519834
It was about understanding how recursion work with class methods, not about practical usage.
0
 
LVL 33

Accepted Solution

by:
sarabande earned 500 total points
ID: 40522305
This will update the object on which the function is being called (the "this" pointer).

Open in new window

no.

*this is dereferencing the pointer to self what is the complex number.

* is the multiplying operator

rec_power(base, n-1) is the recursive call of the rec_power function with the 2nd argument decremented by 1

the rec_power function returns (1,0) for n == 0 what would stop the recursive calling.

the rec_power function returns *this for n == 1 what also would stop the recursive calling.

normally a recursive function only has exactly one stop condition. this also would work here if you would do

comp rec_power(comp base, int n)  const{
        if (n == 0)
            return comp(1,0);
       comp t = (*this) * rec_power(base, n-1);
       return t;
}

Open in new window

you see for n == 1 the return value would be (*this) * (1,0) what is the same as (*this).

in your code the return value is a reference to a temporary and its value is the multiplication of two complex numbers. there is no update to the this what means that the member function can/should  be declared const.

returning a reference to a temporary is bad code as the temporary becomes invalid after scope of the rec_power function. it may work however, if the return value was assigned immidiately to a complex variable. to make it safe code change the return type to returning a comp and not  a comp&.

Sara
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 33

Expert Comment

by:sarabande
ID: 40522312
// investigate why this does not work
//return *this * rec_power(base,  n-1);
i would guess it will be accepted by the compiler if you changed the return type to value type.

i also would recommend to using (*this) to make the statement better readable.

Sara
0
 
LVL 19

Expert Comment

by:mrwad99
ID: 40522355
Sorry about the delay.  Thankfully for you, Sara has participated in this question and has provided, as usual, valuable input :)

You should try to avoid recursion because (depending on how deep you recurse) it can lead to stack overflows (for every recursive call, amongst other actions, stack space is allocated and variable state is saved.  If you recurse too many times, you can run out of stack ("stack overflow")).  

As far as I know, recursion is the same for class methods as it is for none-class methods.

Additionally, when you change the return type of your functions to value, not reference, as both Sara and I suggested,

 return *this * rec_power(base,  n-1);

Open in new window


...is fundamentally no different to ...

comp t = *this * rec_power(base, n-1);
return t;

Open in new window


...except that in the latter, you are creating a named temporary (you call this 't').  The former will still create a 'comp' object, and it will still be copied when it is returned.
0
 

Author Comment

by:Nusrat Nuriyev
ID: 40529892
sarabande,

when I write this

 
   comp rec_power(comp base, int n)
    {
        if (n == 0)
            return comp(1,0);

        comp t = (*this) * rec_power(base, n-1);
        return t;

        // investigate why this does not work
        //return *this * rec_power(base,  n-1);
    }

Open in new window


it returns following:

C:\Complex2\main.cpp|98|error: no match for 'operator*' in '*(comp<double>*)this * comp<T>::rec_power(comp<T>, int) [with T = double; comp<T> = comp<double>](comp<double>((*(const comp<double>*)(& base))), (n + -1))'|
0
 

Author Comment

by:Nusrat Nuriyev
ID: 40529894
// investigate why this does not work
//return *this * rec_power(base,  n-1);

i would guess it will be accepted by the compiler if you changed the return type to value type.

Can't get this.
0
 
LVL 33

Assisted Solution

by:sarabande
sarabande earned 500 total points
ID: 40529948
comp& operator*(comp& second)
the problem is not the dereference operator* but the multiplication operator*. for that you defined an operator function which actually is an operator*= , as it changes the 'this'. because of that definition the compiler doesn't accept a multiplication of *this in another member function.

you should change all operators to their correct prototype what means that they should be const and have const argument wherever it is possible:

// addition (add another comp to *this and return a temporary by value)
comp operator+(const comp & t) const { .. }

// multiplication (multiply another comp to *this and return a temporary by value)
comp operator*(const comp & t) const 
{
        comp temp;
        temp.re = this->re * second.re + (-1)* this->im * second.im;
        temp.im = this->re * second.im + this->im * second.re;
        // here do not change 'this' but return temp by value
        return temp;
}

// the operator*= would be a non-const function:
// multiplication + assignment 
comp &  operator*=(const comp & second)  
{
        comp temp;
        temp.re = this->re * second.re + (-1)* this->im * second.im;
        temp.im = this->re * second.im + this->im * second.re;
        // here the this was modified
        *this = temp;
        return *this;   // return a reference to modified this 
}

Open in new window


generally, for a new type you have to be very strict regarding constness and have to provide all necessary operators. if you don't do you would not be able to use private members for your class.

Sara
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Unlike C#, C++ doesn't have native support for sealing classes (so they cannot be sub-classed). At the cost of a virtual base class pointer it is possible to implement a pseudo sealing mechanism The trick is to virtually inherit from a base class…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

919 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now