Rational Class Built Off of Polynomial Class: An Analysis of Class Dependency and Operator Overloading

1.1k views Asked by At

I have a Polynomial and Rational class which manipulates polynomial and rational functions as vectors. I've defined non-member operators for *, /, +, and -, but I don't think I'm getting how to use them correctly (see code below):

#include<iostream>
#include<algorithm>
#include<iterator>
#include<functional>
#include<vector>
#include<cmath>

using namespace std;

class Polynomial
{
public:
    Polynomial();
    Polynomial(vector<int>coeffs);
    friend class Rational;
     Accessors
    int Degree() const;
    int Coefficient(int k) const;
    void print() const;
    int get_size() const;
    vector<int> get_vect() const; // THIS RETURNS coefficient.
    void set_vect(vector<int> input); // THIS SETS coefficient TO AN INPUTTED VECTOR OF INTEGERS.
    void constantMultiply(int x);
    void Transform();
    double evaluateAt(double x);

    Polynomial& operator++();
    Polynomial operator++ (int unused);
    Polynomial& operator--();
    Polynomial operator-- (int unused);
    Polynomial& operator+=(Polynomial name1);
    Polynomial& operator-=(Polynomial name2);
    Polynomial& operator*=(Polynomial name3);

private:
    vector<int> coefficient;
};

 poly1 + poly2
Polynomial Add(const Polynomial & poly1, const Polynomial & poly2);
 poly1 - poly2
Polynomial Subtract(const Polynomial & poly1, const Polynomial & poly2);
 poly1 * poly2
Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2);

int zero_detect( vector<int> a , int j);
vector<int> flip( vector<int> input );

class Rational
{
public:
    Rational();
    Rational(Polynomial p);
    Rational(Polynomial pN, Polynomial pD);
    double evaluateAt(double x);
    void print();
    Rational& operator++();
    Rational operator++(int unused);
    Rational& operator--();
    Rational operator--(int unused);
    Rational& operator+=(Rational name1);
    Rational& operator-=(Rational name1);
    Rational& operator*=(Rational name1);
    Rational& operator/=(Rational name1);
    Polynomial get_poly_top(); // SOME SIMPLE ACCESSORS.
    Polynomial get_poly_bot();
private:
    Polynomial top;
    Polynomial bot;
};

Polynomial operator+ (Polynomial a , Polynomial b);
Polynomial operator- (Polynomial a , Polynomial b);
Polynomial operator* (Polynomial a , Polynomial b);

Rational operator+ (Rational a , Rational b);
Rational operator- (Rational a , Rational b);
Rational operator* (Rational a , Rational b);
Rational operator/ (Rational a , Rational b);

bool operator== (Polynomial a , Polynomial b);
bool operator!= (Polynomial a , Polynomial b);
bool operator< (Polynomial a , Polynomial b);
bool operator> (Polynomial a , Polynomial b);
Polynomial sign_swap(Polynomial input); // THIS NEGATES HE COEFFICIENT CELLS, AND HELPS WITH DEFINING SUBTRACTION OFF OF ADDITION.

int main(void)
{
    cout << "Welcome! Please input the coefficients of the first polynomial, p." << endl;
    cout << "When you are finished, enter -1234." << endl;

    vector<int> user_vect1;
    vector<int> user_vect2;

    int input1;
    do
    {
        cin >> input1;
        if(input1 == -1234)
        {
            continue;
        }
        else
        {
            user_vect1.push_back(input1);
        }
    }while(input1 != -1234); // THIS IS THE USER INPUT GADGET.

    cout << endl << endl;

    cout << "Your first polynomial is ";

    Polynomial user_poly1(user_vect1);
    Polynomial temp_poly1(user_vect1);
    user_poly1.print();

    cout << "." << endl;

    cout << "Its transform is ";

    user_poly1.Transform();
    user_poly1.print();

    cout << "." << endl << endl;

    cout << "Please input the coefficients of the second polynomial, q." << endl;

    int input2;
    do
    {
        cin >> input2;
        if(input2 == -1234)
        {
            continue;
        }
        else
        {
            user_vect2.push_back(input2);
        }
    }while(input2 != -1234);

    cout << endl << endl;

    cout << "Your second polynomial is ";

    Polynomial user_poly2(user_vect2);
    Polynomial temp_poly2(user_vect2); // I WANTED A TEMPORARY POLYNOMIAL BECAUSE user_poly(i) GETS TRANSFORMED LATER.
    user_poly2.print();

    cout << "." << endl;

    cout << "Its transform is ";

    user_poly2.Transform();
    user_poly2.print();

    cout << "." << endl << endl;

    cout << "p(x)+q(x) = ";
    /*FUNCTION CALL*/
    (temp_poly1+temp_poly2).print();
    cout << endl << endl;

    cout << "p(x)-q(x) = ";
    /* FUNCTION CALL */
    (temp_poly1-temp_poly2).print();
    cout << endl << endl;

    cout << "p(x)*q(x) = ";
    /*FUNCTION CALL */
    (temp_poly1*temp_poly2).print();
    cout << endl << endl;

    cout << "p(x)/q(x) = ";
    /*FUNCTION CALL*/
    Rational user_rat1(temp_poly1,temp_poly2);
    user_rat1.print();
    cout << endl << endl;

    cout << "p(x)/q(x) + p(x)*q(x) = ";
    /*FUNCTION CALL*/
    Rational user_rat2(temp_poly1+(temp_poly1)*(temp_poly2*temp_poly2),temp_poly2);
    (user_rat2).print();
    cout << endl << endl;

    cout << "p(x)+1 = ";
    /*FUNCTION CALL*/
    (++temp_poly1).print();
    cout << endl << endl;

    cout << "p(x)+2 = ";
    /*FUNCTION CALL*/
    (++temp_poly1).print();
    cout << endl << endl;
    --(--temp_poly1);

    cout << "(p(x)/q(x))*(1+x^2-3x^4) = ";
    /*FUNCTION CALL*/
    vector<int> temp_insert;
    temp_insert.push_back(1);
    temp_insert.push_back(0);
    temp_insert.push_back(1);
    temp_insert.push_back(0);
    temp_insert.push_back(-3); // HERE I'M PUSHING THE VALUES OF THE DESIRED POLYNOMIAL INTO temp_insert.
    Polynomial temporary(temp_insert);
    Rational temp_rat1(temporary);
    (user_rat1*temp_rat1).print(); // <-- RIGHT HERE IS THE BIGGEST ISSUE I'M HAVING. IT'S NOT .print() I DON'T THINK.
    cout << endl << endl;

    cout << "Does p(x) equal q(x)? ";
    /*FUNCTION CALL*/ //<--- Should be a function that is a void, but outputs "Yes." or "No."
    if( temp_poly1 == temp_poly2 )
    {
        cout << "Yes.";
    }
    else
    {
        cout << "No.";
    }
    cout << endl << endl;

    cout << "Is p(x) < q(x)? ";
    /*FUNCTION CALL*/ //<--- Should be a function that is a void, but outputs "Yes." or "No."
    if( temp_poly1 < temp_poly2 )
    {
        cout << "Yes.";
    }
    else
    {
        cout << "No.";
    }
    cout << endl << endl;

    cout << "p(2) = ";
    /*FUNCTION CALL*/
    temp_poly1.evaluateAt(2);
    cout << endl << endl;

    cout << "p(3)/q(3)= ";
    /*FUNCTION CALL*/
    double fun1 = temp_poly1.evaluateAt(3);
    double fun2 = temp_poly2.evaluateAt(3);
    cout << fun1/fun2;
    cout << endl << endl;
};

Polynomial::Polynomial()
{
    coefficient.push_back(0);
}

Polynomial::Polynomial(vector<int> coeffs)
{
    coefficient = coeffs;
}

int Polynomial::Degree() const
{
    int deg = 0;
    for (size_t i = 0; i < coefficient.size(); ++i)
    {
        if (coefficient[i] != 0)
        {
            deg = i;
        }
    }
    return deg;
}

int Polynomial::Coefficient(int k) const
{
    return coefficient[k + 1];
}

void Polynomial::print() const
{
    for( size_t i = 0 ; i < coefficient.size() ; ++i )
    {
        if( coefficient[i] == 0 )
        {
            continue;
        }
        else
        {
            if( i == 0 )
            {
                cout << coefficient[i];
            }
            else
            {
                if(zero_detect(coefficient, i) == i)
                {
                    if( coefficient[i] == 1 || coefficient[i] == -1 )
                    {
                        if( coefficient[i] == 1)
                        {
                            cout << "";
                        }
                        else
                        {
                            cout << "-";
                        }
                    }
                    else
                    {
                        cout << coefficient[i];
                    }
                    if( i == 1 )
                    {
                        cout << "x";
                    }
                    else
                    {
                        cout << "x^" << i;
                    }
                }
                else
                {
                    cout << "+";
                    if( coefficient[i] == 1 || coefficient[i] == -1 )
                    {
                        if( coefficient[i] == 1)
                        {
                            cout << "";
                        }
                        else
                        {
                            cout << "-";
                        }
                    }
                    else
                    {
                        cout << coefficient[i];
                    }
                    if( i == 1 )
                    {
                        cout << "x";
                    }
                    else
                    {
                        cout << "x^" << i;
                    }
                }
            }
        }   
    }
}

int Polynomial::get_size() const
{
    return coefficient.size();
}

vector<int> Polynomial::get_vect() const
{
    return coefficient;
}

void Polynomial::constantMultiply(int x)
{
    for( size_t i = 0 ; i < coefficient.size() ; ++i )
    {
        coefficient[i] *= x;
    }
}

void Polynomial::Transform()
{
    vector<int> transform;
    for( size_t i = 1 ; i < coefficient.size() ; ++i )
    {
        transform.push_back(coefficient[i]*i);
    }
    coefficient = transform;
}

double Polynomial::evaluateAt(double x)
{
    double product=0;
    for(size_t i = 0 ; i < coefficient.size() ; ++i )
    {
        product += (double)coefficient[i]*pow(x,(double)i);
    }
    return product;
}

Polynomial Add(const Polynomial& poly1, const Polynomial& poly2)
{
    vector<int> Poly1 = poly1.get_vect();
    vector<int> Poly2 = poly2.get_vect();
    vector<int> Poly3;

    if( Poly1.size() < Poly2.size() )
    {
        for(size_t i = Poly1.size() ; i< Poly2.size() ; ++i )
        {
            Poly1.push_back(0);
        }
    }
    else if( Poly1.size() > Poly2.size() )
    {
        for(size_t i = Poly2.size() ; i< Poly1.size() ; ++i )
        {
            Poly2.push_back(0);
        }
    }
    for( size_t i = 0 ; i < max(Poly1.size(),Poly2.size()) ; ++i )
    {
        Poly3.push_back(Poly1[i]+Poly2[i]);
    }
    return Poly3;
}

Polynomial Subtract(const Polynomial & poly1, const Polynomial & poly2)
{
    vector<int> Poly1 = poly1.get_vect();
    vector<int> Poly2 = poly2.get_vect();
    vector<int> Poly3;

    if( Poly1.size() < Poly2.size() )
    {
        for(size_t i = Poly1.size() ; i< Poly2.size() ; ++i )
        {
            Poly1.push_back(0);
        }
    }
    else if( Poly1.size() > Poly2.size() )
    {
        for(size_t i = Poly2.size() ; i< Poly1.size() ; ++i )
        {
            Poly2.push_back(0);
        }
    }
    for( size_t i = 0 ; i < max(Poly1.size(),Poly2.size()) ; ++i )
    {
        Poly3.push_back(Poly1[i]-Poly2[i]);
    }
    return Poly3;
}

Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2)
{
    if( poly2.get_size()==1 && poly2.Coefficient(0)==1)
    {
        return poly1;
    }
    else
    {
        vector<int> Poly1 = poly1.get_vect();
        vector<int> Poly2 = poly2.get_vect();
        vector<int> Poly3;

        Poly3.resize(Poly1.size() + Poly2.size() - 1, 0);

        for (size_t i = 0; i != Poly1.size(); i++)
            for (size_t j = 0; j != Poly2.size(); j++)
                Poly3[i+j] += Poly1[i] * Poly2[j];

        return Poly3;
    }
}

int zero_detect( vector<int> a , int j)
{
    int count=0;
    for( size_t i = 0 ; i < j ; ++i )
    {
        if( a[i] == 0 )
        {
            ++count;
        }
    }
    return count;
}

Rational::Rational()
{
    vector<int> temp;
    temp.push_back(0);
    top.set_vect(temp);
    ++bot;
}

Rational::Rational(Polynomial p)
{
    top = p;
    ++bot;
}

Rational::Rational(Polynomial pN, Polynomial pD)
{
    top = pN;
    bot = pD;
}

double Rational::evaluateAt(double x)
{
    return top.evaluateAt(x)/bot.evaluateAt(x);
}

void Rational::print()
{
    top.print();
    cout << " / ";
    bot.print();
}

Polynomial operator+ (Polynomial a , Polynomial b)
{
    return Add(a,b);
}
Polynomial operator- (Polynomial a , Polynomial b)
{
    return Subtract(a,b);
}
Polynomial operator* (Polynomial a , Polynomial b)
{
    return Multiply(a,b);
}

Rational operator+ (Rational a , Rational b)
{
    Rational c((a.get_poly_top()*b.get_poly_bot())+(b.get_poly_top()*a.get_poly_bot()), a.get_poly_bot()*b.get_poly_bot());
    return c;
}
Rational operator- (Rational a , Rational b)
{
    Rational c((a.get_poly_top()*b.get_poly_bot())+(sign_swap(b.get_poly_top()*a.get_poly_bot())), a.get_poly_bot()*b.get_poly_bot());
    return c;
}
Rational operator* (Rational a , Rational b)
{
    Rational c(a.get_poly_top()*b.get_poly_top(), a.get_poly_bot()*b.get_poly_bot());
    return c;
}
Rational operator/ (Rational a , Rational b)
{
    Rational c(a.get_poly_top()*b.get_poly_bot(), a.get_poly_bot()*b.get_poly_top());
    return c;
}

Rational& Rational::operator++()
{
    Rational c(bot, bot);
    return *this+c;
}

Rational Rational::operator++(int unused)
{
    Rational copy(*this);
    Rational c(bot, bot);
    *this = *this+c;
    return copy;
}
Rational& Rational::operator--()
{
    Rational c(bot, bot);
    return *this-c;
}

Rational Rational::operator--(int unused)
{
    Rational copy(*this);
    Rational c(bot, bot);
    *this = *this-c;
    return copy;
}

bool operator== (Polynomial a , Polynomial b)
{
    vector<int>temp1=a.get_vect();
    vector<int>temp2=b.get_vect();
    if( a.Degree() != b.Degree() )
    {
        return false;
    }
    else
    {
        for(size_t i = 0 ; i<a.get_size() ; ++i)
        {
            if( temp1[i]!= temp2[i])
            {
                return false;
            }
        }
        return true;
    }
}
bool operator!= (Polynomial a , Polynomial b)
{
    return !(a==b);
}
bool operator< (Polynomial a , Polynomial b)
{
    if(a.Degree() < b.Degree())
    {
        return true;
    }
    else
    {
        return false;
    }
}
bool operator> (Polynomial a , Polynomial b)
{
    if(a.Degree() > b.Degree())
    {
        return true;
    }
    else
    {
        return false;
    }
}

Polynomial Rational::get_poly_top()
{
    return top;
}

Polynomial Rational::get_poly_bot()
{
    return bot;
}

Polynomial sign_swap(Polynomial input)
{
    vector<int> temp = input.get_vect();
    for(size_t i = 0 ; i<input.get_size() ; ++i )
    {
        temp[i] *=-1;
    }
    input.set_vect(temp);
    return input;
}

void Polynomial::set_vect(vector<int> input)
{
    coefficient = input;
}

Polynomial& Polynomial::operator++()
{
    coefficient[0]++;
    return *this;
}
Polynomial Polynomial::operator++ (int unused) // &
{
    Polynomial copy(*this);
    coefficient[0]++;
    return copy;
}
Polynomial& Polynomial::operator--()
{
    coefficient[0]--;
    return *this;
}
Polynomial Polynomial::operator-- (int unused) // &
{
    Polynomial copy(*this);
    coefficient[0]--;
    return copy;
}
Polynomial& Polynomial::operator+=(Polynomial name1)
{
    return Add(*this, name1);
}
Polynomial& Polynomial::operator-=(Polynomial name2)
{
    return Subtract(*this, name2);
}
Polynomial& Polynomial::operator*=(Polynomial name3)
{
    return Multiply(*this, name3);  
}

I get an error that says I've got an out-of-range issue with some vector process in the code.


Note:

If you are taking a programming class, and this happens to be your assignment, then please do not copy and paste this code into your source and use it for your own benefit. Instead, use it as a foundation to build off of if you're having trouble.


Any help with resolving this rational multiplication issue, or anything else that seems inefficient, redundant, useless, etc. would be much appreciated. Thank you. :-)


The Problem:

I've created a Rational class that is friend to a Polynomial class, and the one-argument constructor Rational( Polynomial p) sets its top polynomial top to p, which is of data type Polynomial, and sets its bottom polynomial bot to 1, which is of the same data type as top. I've created a Rational object in main using this one-argument constructor passing in a vector I generated manually in main, but when I try to print the product of two rational objects--the first one, user_rat1, being a two-argument type construction with top=p and bot=1 (1 the polynomial)--I get an error saying the bounds of the vector are out of range. I don't see why...

2

There are 2 answers

0
KugBuBu On

Source:

Polynomial Multiply(const Polynomial & poly1, const Polynomial & poly2)
{
    if( poly2.get_size()==1 && poly2.Coefficient(0)==1)

The problemic method:

int Polynomial::Coefficient(int k) const
{
    return coefficient[k + 1];
}

If the size is 1 then you can only reach the coefficient[0] and k + 1 here is 1. You may meant:

int Polynomial::Coefficient(int k) const
{
    return coefficient[k];
}
0
Sahar Yehezkel On

Made sure that you understand the coefficients array/vector's index mean the exponent.

I can suggest for you to use another int data type that hold your degree (for any poly). (in addition you can add another int data type that hold the currentDegree = the highest degree in the poly that != 0).

For example, if you want to create new Polynomial with highest degree = 4.

Polynomial::Polynomial(int degree){
    this->degree = degree;
    if(degree == 0)
        this->coeffs = new double();
    else if (degree > 1)
        this->coeffs = new double[degree+1];
    else if (degree == 1)
        this->coeffs = new double();
    for(int i=0;i<=degree;i++)
        this->coeffs[i] = 0;
    actualDegree = 0;
}

in addition, you can add another constructor when you get array for example:

Polynomial::Polynomial(double* coeffs, int degree){
    this->degree = degree;
    this->actualDegree = 0;
    this->coeffs = new double[degree+1];
    for(int i=0;i<=degree;i++){
        this->coeffs[i] = coeffs[i];
        if (coeffs[i] != 0 && i > actualDegree)
            actualDegree = i;
    }
}

That will help you in functions when you use any object from Polynomial to know your degree for any object you working with. If you want you can even made the constructor as template for int\double (but dont forget to set it in class to the pointer)