简体   繁体   中英

C++ Polynomial addition

I am trying to add two polynomials in C++ and I'm lost as to where to even start. So the user can enter values for a polynomial, they do not need to be in order or anything.

For example it can be: Poly 1: 2x^5 + 5x^2 - 2x + 9 Poly 2: x^2 + 0

I have coefficient and exponent stored in the class (objects) private fields. So would I look at the first exponent in Poly 1, search Poly 2 for same exponent first and if found add them? Then go on to the second term?

Code as requested: (NOTE: The implementation is currently wrong and I need help on how to work through this problem.)

#include <cmath>
#include <iostream>
using namespace std;

class polynomial
{
public:
polynomial();
polynomial(int);
polynomial(int exponent[], int coefficient[], int);
~polynomial();
polynomial &operator = (const polynomial &obj);
int evaluate(double uservalue);
polynomial operator+(const polynomial &obj) const;
void operator-(const polynomial &obj) const;
void operator*(const polynomial &obj) const;
friend istream & operator>> (istream & in, polynomial &obj);
friend ostream & operator<< (ostream & out, const polynomial &obj);
friend void growone(polynomial &obj);
private:
int *coefficient;
int *exponent;
int size;
};

And the implementation

polynomial polynomial::operator+(const polynomial &obj) const
{
    bool matchFound = false;
    polynomial tmp;
    if (size >= obj.size) {
        for (int i = 0; i < size; i++) {
            if (i >= tmp.size) {
                growone(tmp);
            }
            for(int y = 0; i < obj.size; i++) {
                if (exponent[i] == obj.exponent[y]) {
                    tmp.coefficient[i] = (coefficient[i]+obj.coefficient[y]);
                    tmp.exponent[i] = exponent[i];
                    tmp.size++;
                    matchFound = true;
                }
            }
            if (matchFound == false) {
                tmp.coefficient[i] = coefficient[i];
                tmp.exponent[i] = exponent[i];
                tmp.size++;
            }
            matchFound = false;
        }
    } else {



    }
    return tmp;
}

You're not really using the power of C++ to its fullest there. A good rule is that, if you are using non-smart pointers for anything, you should step back and have a rethink.

It's no accident that a large number of questions about C on Stack Overflow have to do about problems with pointers :-)

The other point I would add is that it may be worth actually wasting a small amount of memory to greatly simplify your code. By that, I mean don't try to create sparse arrays to hold your terms (coefficient-exponent pairs). Instead, allow each expression to hold every term up to its maximum, with the coefficients for the unused ones simply set to zero. Unless you have an expression like 4x 99999999999999 + 3 , the amount of extra memory taken may be worth it.

To that end, I'd propose using a std::vector for just the coefficients starting at an exponent of zero. The exponents are actually decided by the position within the vector. So the expression 4x 9 - 17x 3 + 3 would be stored as the vector:

{3, 0, 0, -17, 0, 0, 0, 0, 0, 4}
 0 <------- exponent -------> 9

That actually makes the task of adding and subtracting polynomials incredibly easy since the coefficients are all nicely lined up.


So, with that in mind, let's introduce a cut-down class for showing how it's done:

#include <iostream>
#include <vector>

using std::cout;
using std::vector;
using std::ostream;

class Polynomial {
public:
    Polynomial();
    Polynomial(size_t expon[], int coeff[], size_t sz);
    ~Polynomial();
    Polynomial &operator=(const Polynomial &poly);
    Polynomial operator+(const Polynomial &poly) const;
    friend ostream &operator<<(ostream &os, const Polynomial &poly);
private:
    std::vector<int> m_coeff;
};

The default constructor (and the destructor) are very simple, we just ensure that an initialised polynomial always has at least one term:

Polynomial::Polynomial() { m_coeff.push_back(0); }
Polynomial::~Polynomial() {}

The constructor-from-array is a little more complex because we want to, as early as possible, turn the user's "anything goes" format into something we can use easily:

Polynomial::Polynomial(size_t expon[], int coeff[], size_t sz) {
    // Work out largest exponent and size vector accordingly.

    auto maxExpon = 0;
    for (size_t i = 0; i < sz; ++i) {
        if (expon[i] > maxExpon) {
            maxExpon = expon[i];
        }
    }
    m_coeff.resize(maxExpon + 1, 0);

    // Fill in coefficients.

    for (size_t i = 0; i < sz; ++i) {
        m_coeff[expon[i]] = coeff[i];
    }
}

Now you'll see why we made the decision to not use sparse arrays and to place the zero exponent at the start of the vector. Bothe operator= and operator+ are simple because they already know where all terms are:

Polynomial &Polynomial::operator=(const Polynomial &poly) {
    if (this != &poly) {
        m_coeff.clear();
        for (int coeff: poly.m_coeff) {
            m_coeff.push_back(coeff);
        }
    }
    return *this;
}

Polynomial Polynomial::operator+(const Polynomial &poly) const {
    // Create sum with required size.

    size_t thisSize = this->m_coeff.size();
    size_t polySize = poly.m_coeff.size();

    Polynomial sum;
    if (thisSize > polySize) {
        sum.m_coeff.resize(thisSize, 0);
    } else {
        sum.m_coeff.resize(polySize, 0);
    }

    // Do the actual sum (ignoring terms beyond each limit).

    for (size_t idx = 0; idx < sum.m_coeff.size(); ++idx) {
        if (idx < thisSize) sum.m_coeff[idx] += this->m_coeff[idx];
        if (idx < polySize) sum.m_coeff[idx] += poly.m_coeff[idx];
    }

    return sum;
}

Now we just need to complete this with an output function and a small test mainline:

ostream &operator<< (ostream &os, const Polynomial &poly) {
    bool firstTerm = true;
    if (poly.m_coeff.size() == 1 && poly.m_coeff[0] == 0) {
        os << "0";
        return os;
    }

    for (size_t idx = poly.m_coeff.size(); idx > 0; --idx) {
        if (poly.m_coeff[idx - 1] != 0) {
            if (firstTerm) {
                os << poly.m_coeff[idx - 1];
            } else if (poly.m_coeff[idx - 1] == 1) {
                os << " + ";
                if (idx == 1) {
                    os << poly.m_coeff[idx - 1];
                }
            } else if (poly.m_coeff[idx - 1] == -1) {
                os << " - ";
            } else if (poly.m_coeff[idx - 1] < 0) {
                os << " - " << -poly.m_coeff[idx - 1];
            } else {
                os << " + " << poly.m_coeff[idx - 1];
            }
            if (idx > 1) {
                os << "x";
                if (idx > 2) {
                    os << "^" << idx - 1;
                }
            }
            firstTerm = false;
        }
    }
    return os;
}

int main() {
    int    c1[] = {1, 2, 3, 4, 5};
    size_t e1[] = {3, 1, 4, 0, 9};
    Polynomial p1(e1, c1, (size_t)5);
    cout << "Polynomial 1 is " << p1 << " (p1)\n";

    int    c2[] = {6, 7, 8};
    size_t e2[] = {3, 7, 9};
    Polynomial p2(e2, c2, (size_t)3);
    cout << "Polynomial 2 is " << p2 << " (p2)\n";

    Polynomial p3 = p1 + p2;
    cout << "Polynomial 3 is " << p3 << " (p3 = p1 = p2);
}

And the output, which I've slightly reformatted to show like terms, shows it in action:

Polynomial 1 is   5x^9 +        3x^4 +  x^3 + 2x + 4
Polynomial 2 is   8x^9 + 7x^7 +        6x^3
                 ===================================
Polynomial 3 is  13x^9 + 7x^7 + 3x^4 + 7x^3 + 2x + 4

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM