0

I'm in the process of writing a Polynomial Class and have overloaded the + operator. I asked a question a few days ago regarding the actual overloading process, and received a great answer. However, my question now is in regards to the actual function of my program.

I need to add two user entered polynomials together. When one adds polynomials one must only add like terms, even if the two polynomials differ in size. My program does ok if the first entered polynomial is larger than the second, but reaches an error if the first polynomial is smaller than the second. To be more specific... I've noticed that it seems to leave one term off. On top of that it seems to add two like terms together and then print it with a different exponent. For example : 2x^3 + 3x^3 = 5x^2.

For reference, this is my previous question regarding this program: Overloading + operator with classes containing array pointers (C++)

Some help would be greatly appreciated.

My Code:

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

#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H

class Polynomial 
{
      friend istream& operator>>(istream& in, Polynomial& p);
      friend ostream& operator<<(ostream& out, const Polynomial& p);
      public:
             Polynomial(int = 10);
             ~Polynomial();
             void assignExponent();
             Polynomial operator+(const Polynomial& other);

      private:
              int SIZE;
              int *exponents;
              int *polyPtr; 
};

#endif

//CONSTRUCTOR
Polynomial::Polynomial(int arraySize)
{
     if(arraySize > 0)
                  SIZE = arraySize;
     else
     {
         cout << "Array size must be greater than 0. Program will now "
              << "Terminate..." << endl;

         system("pause");
         exit(0);
     }

     polyPtr = new int[SIZE]; 
     exponents = new int[SIZE];

     for(int i = 0; i<SIZE; i++)
             polyPtr[i] = 0;

     assignExponent();
};

//DESTRUCTOR
Polynomial::~Polynomial() 
{
     delete [] polyPtr;                         
};

//STREAM INSERTION
istream& operator>>(istream& in, Polynomial& p)
{
         for(int i = 0; i<p.SIZE; i++)
         {
               in >> p.polyPtr[i];         
         }

         return in;
};

//STREAM EXTRACTION
ostream& operator<<(ostream& out, const Polynomial& p)
{
         int exponent;
         for(int i = 0; i<p.SIZE; i++)
         {
               exponent = (p.SIZE - 1) - i;

               if(p.polyPtr[i] != 1)
               {  
                  if(exponent > 0 && exponent != 1)
                           out << p.polyPtr[i] << "x^" << exponent << " + ";  

                  if(exponent == 1)
                           out << p.polyPtr[i] << "x" << " + ";

                  if(exponent == 0)
                           out << p.polyPtr[i];  
               }

               //In order to not display coefficient if = 1
               else
               {
                   if(exponent > 0 && exponent != 1)
                           out << "x^" << exponent << " + ";  

                   if(exponent == 1)
                           out << "x" << " + ";

                   if(exponent == 0)
                           out << p.polyPtr[i];
               }    
         }       

         return out;
}; 

//Assigns a value for exponent
void Polynomial::assignExponent()
{
     for(int i = 0; i<SIZE; i++)
     {
             exponents[i] = (SIZE - 1) - i;        
     }
};

//OVERLOAD OF + OPERATOR
Polynomial Polynomial::operator+(const Polynomial& other)
{
         Polynomial sum(SIZE);
         int difference;

         //If the first polynomial is larger
         if (SIZE > other.SIZE)
         {
            difference = SIZE - other.SIZE;

            for(int i = 0; i<SIZE; i++)
            {
                 if(i - difference < 0)
                      sum.polyPtr[i] = polyPtr[i];

                 else
                 {
                     sum.polyPtr[i] = polyPtr[i] + 
                                  other.polyPtr[i - difference];  
                 }                            
            }         
         }

         //If the second polynomial is larger       **PROBLEM***************************************  
         if(other.SIZE > SIZE)
         {
            difference = other.SIZE - SIZE;

            for(int i = 0; i<other.SIZE; i++)
            {
                 if(i - difference < 0)
                      sum.polyPtr[i] = other.polyPtr[i];

                 else
                 {
                     sum.polyPtr[i] = other.polyPtr[i] + 
                                  polyPtr[i - difference];  
                 }                            
            }         
         }

         //If the polynomials are equal
         if(SIZE == other.SIZE)     
         {
                  for(int i = SIZE-1; i >= 0; i--)
                  {
                          sum.polyPtr[i] = polyPtr[i] + other.polyPtr[i];        
                  }   
         }

         return sum;
};

int main()
{
    int polySize;

    //User enters a size for the first & second polynomial
    cout << "Enter a size for the first polynomial: ";
    cin >> polySize;
    Polynomial pOne(polySize);

    cout << "\nEnter a size for the second polynomial: ";
    cin >> polySize;
    Polynomial pTwo(polySize);

    //User enters in values (Overload of >> operator
    cout << "\n\nEnter in values for the first polynomial, "
         << "in the format - (x x x x): " << endl;
    cin >> pOne;
    cout << "\nEnter in values for the second polynomial, "
         << "in the format - (x x x x): " << endl;
    cin >> pTwo;

    //Overload << operator for output
    cout << "\nPolynomial 1 is: " << pOne << endl
         << "Polynomial 2 is: " << pTwo << endl;

    Polynomial pThree = pOne + pTwo;

    cout << "\nAfter being added together, the new polynomial is: "
         << pThree << endl;

 system("pause");   
}

Output Window: enter image description here

Community
  • 1
  • 1
Eric after dark
  • 1,768
  • 4
  • 31
  • 79
  • I can't reproduce this error. The results seem correct. 2x^3 + 3x^3 = 5x^3. Could you post a simplified version of `main` without all the user input, that reproduces the error? – Beta Mar 15 '13 at 13:24
  • Shouldn't the `SIZE` of `sum` be `max(SIZE,other.SIZE)`? Currently, your `sum` is always as large as the `Polynomial` you're doing the operation on, instead of the size of the largest of the two. – JSQuareD Mar 15 '13 at 13:26
  • I have updated my post with an output window. @JSQuareD: You're absolutely right, I have changed my code and it worked! Thank you! – Eric after dark Mar 15 '13 at 13:31

4 Answers4

4

The SIZE of sum should be the maximum of the SIZE of the two polynomials:

Polynomial Polynomial::operator+(const Polynomial& other)
{
         Polynomial sum( max(SIZE,other.SIZE) );

Otherwise your new Polynomial is only as large as the polynomial you're doing the operation on, and you will be writing to unallocated memory further down the loop:

for(int i = 0; i<other.SIZE; i++)
{
     if(i - difference < 0)
          sum.polyPtr[i] = other.polyPtr[i];

     else
     {
         sum.polyPtr[i] = other.polyPtr[i] + 
                      polyPtr[i - difference];  // i may be higher than SIZE, thus sum.polyPtr[i] invokes undefined behaviour.
     }                            
}  
JSQuareD
  • 4,641
  • 2
  • 18
  • 27
4

The current first problem is here:

 Polynomial sum(SIZE);

Better:

 Polynomial sum(std::max(SIZE, other.SIZE));

But I think the real problem is that you need to simplify your design. The first thing could be to use:

      private:
              int    SIZE;
              double *coef;
};

Simple keep the coeficient for ax^n in coef[n]=a. Now is tryvial to find out what elemnt you need to add.

But much simpler could be to use std::map<int,double> p; to store all. p[n]=a;

Without debugging and optimizing, just an idea:

      private:
             std::map<int,double> p; 
};

And forget about any new, delete and index out of range.

The +() will be like:

Polynomial Polynomial::operator+(const Polynomial& other)
{
   Polynomial sum;  // No SIZE more.
   sum.p= p;
   for (auto ax_n : other.p)
      sum.p[ax_n.first] += ax_n.second;
   return sum;
 }
qPCR4vir
  • 3,521
  • 1
  • 22
  • 32
2

Your problem lies in the construction of sum(SIZE)

Polynomial Polynomial::operator+(const Polynomial& other)
{
         Polynomial sum(SIZE);

If you do this, and the first polynomial is only of size 2, later in the method you are copying into memory that isn't yours:

     if(other.SIZE > SIZE)
     {
        difference = other.SIZE - SIZE;

////HERE IS YOUR PROBLEM - your loop uses other.SIZE, which is larger than SIZE...

        for(int i = 0; i<other.SIZE; i++)
        {
             if(i - difference < 0)
                  sum.polyPtr[i] = other.polyPtr[i];

             else
             {
                 sum.polyPtr[i] = other.polyPtr[i] + 
                              polyPtr[i - difference];  
             }                            
        }         
     }

The error happens because you use sum.polyPtr[i], which when the SIZE < other.SIZE occurs, doesn't exist.

Silas
  • 406
  • 2
  • 11
1

Your code is way too over-complicated. Something like this does it nicely:

#include <algorithm>
#include <iostream>
#include <vector>
#include <iterator>
#include <sstream>

// helper to read the input polynomials into a output-iterator
template<class OutIter>
void read_vector(std::istream& is, OutIter first)
{
        // helper type to iterate over the input coefficients
        typedef std::istream_iterator<
                typename OutIter::container_type::value_type> iter_t;
        // buffer to hold the input line
        std::string buffer;
        // read it
        std::getline(is, buffer);
        // create a string stream with which we tokenize the input
        std::istringstream iss(buffer);
        // read coefficients into output container
        std::copy(iter_t(iss), iter_t(), first);
}

int main()
{
        std::vector<double> p1, p2;

        // read input
        std::cout << "Enter coefficients of the first polynomial: ";
        read_vector(std::cin, std::back_inserter(p1));
        std::cout << "Enter coefficients of the second polynomial: ";
        read_vector(std::cin, std::back_inserter(p2));

        // check for errors
        if (p1.empty() || p2.empty())
        {
            std::cerr << "Error: polynomials must not be empty\n";
            return 1;
        }

        // initialize result polynomial to 0. coefficients
        std::vector<double> p3(std::max(p1.size(), p2.size()), 0.);
        // copy first polynomial to the result, starting from the back
        std::copy(p1.rbegin(), p1.rend(), p3.rbegin());
        // add second polynomial, starting from the back
        std::transform(p2.rbegin(), p2.rend(), p3.rbegin(), p3.rbegin(),
                       std::plus<double>());

        // print result
        std::cout << "Sum: ";
        const size_t n = p3.size()-1;
        for (size_t i=0; i < n; ++i)
        {
                std::cout << std::showpos << p3[i] << "x^" << n-i;
        }
        std::cout << std::showpos << p3[n] << "\n";
}
Michael Wild
  • 24,977
  • 3
  • 43
  • 43
  • :-) I don't think it's particularly smart, I'm sure there are some code-wizards who would solve this much better than I did. But it should give you and other new programmers an idea what to look for in C++ code. – Michael Wild Mar 18 '13 at 05:04
  • In all honesty, some of it I don't really understand. – Eric after dark Mar 18 '13 at 12:21
  • 1
    Then you got some reading to do ;-) I suggest a good C++ book, perhaps one from this [list](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Michael Wild Mar 18 '13 at 12:25