All pastes #906180 Raw Edit

Untitled

public text v1 · immutable
·published 2008-02-16 12:24 UTC
rendered paste body
#ifndef POLYNOMIAL_H
#define POLYNOMIAL_H
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>

namespace Doug { // end of namespace at end of file

class Monomial {
     friend class Polynomial;
     public:
          Monomial( const double ctorCoefficient = 0, const double ctorExponent = 0 )
                    : coefficient(ctorCoefficient), exponent(ctorExponent) {
               ; // constructor not used by current driver but made
                 // available for other drivers that might
          }
          Monomial( const Monomial& m ) {
               coefficient = m.coefficient;
               exponent    = m.exponent; 
          }
          ~Monomial() {
               ; // nothing needs to be done
          }
          
          // Getters and setters are provided for classes that
          // may wish to utilize Monomials but which are not
          // friend classes.  Polynomials are closely related
          // to Monomials and so are made a friend class with
          // full access to the internal data of a Monomial.          
          // This is more efficient, and not a great risk.
          
          // With the benefit of hindsight, Monomial might have
          // been better implemented as a struct or as std::pair
          // because it doesnt really provide any behavior...
          // ...except the operator== which may justify it being
          // a class... although it could be a struct with a
          // non-member operator==
          void setCoefficient(double newCoefficient) {
               coefficient = newCoefficient;
          }
          void setExponent(double newExponent) {
               exponent = newExponent;
          }
          double getCoefficient() const {
               return coefficient;
          }
          double getExponent() const {
               return exponent;
          }
          
          // Operator== is used in the std::remove operation
          // which is used in Polynomial operator-=
          bool operator==(const Monomial& rhs) {
               if ( coefficient == rhs.coefficient && exponent == rhs.exponent ) {
                    // if they are exactly equal, they match
                    return true;
               } else if ( coefficient == 0 && rhs.coefficient == 0 ) {
                    // the exponent doesn't matter if they coefficients are 0
                    // so they match if their coefficients are both 0
                    return true;
               } else { // not a match
                    return false;
               }
          }
     private:
          double coefficient; // aka constant, multiplied by variable
          double    exponent; // ... whole number exponent aka degree
};

class Polynomial {
     public:
          Polynomial() {
               ; // nothing needs to be done
          }
          Polynomial ( const Polynomial& p ) {
               // copy constructor not used for current driver
               // but may be used by other drivers
               this->terms = p.terms;
          }
          ~Polynomial() {
               ; // nothing needs to be done
          }
          
          void enterTerms() {
               // appends inputted terms to the polynomial
               std::string input("y");
               do {
                    if ( input.length() == 1 && tolower(input[0]) == 'y' ) {
                         enterTerm();
                    } else if ( (input.length() == 1 && tolower(input[0]) != 'n' ) || input.length() > 1 ) {
                         std::cout << "\n Invalid input.";
                    }
                    std::cout << "\n Another term? (Y/N) : > ";
                    std::cin.ignore();
                    std::getline(std::cin, input);
               } while( tolower(input[0]) != 'n' || input.length() > 1  );
          }
          
          // intentionally left available to driver programs even
          // though it is not utilized in the test driver
          void enterTerm() {
               Monomial monomial;
               std::string input;
               std::cout << "\n Enter coefficient   : > ";
               std::cin  >> monomial.coefficient;
//               std::cout << "\n Coefficient is      :   " << monomial.coefficient;
               std::cout << "\n Enter exponent      : > ";
               std::cin  >> monomial.exponent;
//               std::cout << "\n Exponent is         :   " << monomial.exponent;
               terms.push_back(monomial);
          }
          /* determined to be unnecessary but might be
             reimplemented for some purpose later
          Monomial getTerm(const size_t term) const {
               return terms[term];
          }*/
          void printPolynomial() const {
               if ( terms.size() > 0 ) {
                    for ( size_t i = 0; i < terms.size(); ++i ) {
                         printTerm(i);
                         if ( i < terms.size() - 1 ) {
                              std::cout << " + ";
                         }
                    }
               } else {
                    std::cout << '0';
               }
          }
          Polynomial operator+=( const Polynomial& rhs ) {
               for ( std::vector<Monomial>::const_iterator rTerm = rhs.terms.begin();
                         rTerm != rhs.terms.end(); ++rTerm ) {
                    bool match = false;
                    for ( std::vector<Monomial>::iterator term = terms.begin();
                              term != terms.end(); ++term ) {
                         // loop through each of the current object's terms
                         // and if they have the same exponent, add their coefficients
                         if ( term->exponent == rTerm->exponent ) {
                              term->coefficient += rTerm->coefficient;
                              match = true;
                              break;
                         }
                    }
                    // if there is no term with the same exponent
                    // then add the term as a new separate term
                    if ( match == false ) {
                         terms.push_back(*rTerm);
                    }
               }
               return *this;
          }
          Polynomial operator-=( const Polynomial& rhs ) {
               for ( std::vector<Monomial>::const_iterator rTerm = rhs.terms.begin();
                         rTerm != rhs.terms.end(); ++rTerm ) {
                    bool match = false;
                    for ( std::vector<Monomial>::iterator term = terms.begin();
                              term != terms.end(); ++term ) {
                         // loop through each of the current object's terms
                         // and if they have the same exponent, subtract the coefficient
                         if ( term->exponent == rTerm->exponent ) {
                              term->coefficient -= rTerm->coefficient;
                              match = true;
                              break;
                         }
                    }
                    // if there is no term with the same exponent
                    // then add the term as a new separate term
                    if ( match == false ) {
                         terms.push_back(*rTerm);
                         terms.back().coefficient -= terms.back().coefficient * 2;
                    }
               }
               // remove terms that have been negated/cancelled out
               const Monomial zero;
               terms.erase(std::remove(terms.begin(), terms.end(), zero), terms.end());
               return *this;
          }
          Polynomial operator*=( const Polynomial& rhs ) {
               Polynomial products;
               // x*x becomes x^2, 2x*x becomes 2x^2
               // x^2 * x^2 becomes x^4 ie. x*x * x*x = x*x*x*x
               // (x + x^2) + (x + x^2) = 2x + 2x^2;
               // (x + x^2) * (x + x^2) = x^2 + x^3 + x^3 + x^4 = x^2 + 2x^3 + x^4
               // above are examples used to design the algorithm
               for ( std::vector<Monomial>::const_iterator rTerm = rhs.terms.begin();
                         rTerm != rhs.terms.end(); ++rTerm ) {
                    for ( std::vector<Monomial>::iterator term = terms.begin();
                              term != terms.end(); ++term ) {
                         // create a new term for each combination of terms from lhs & rhs
                         // and do simple multiplication that way, then add the products
                         products.terms.push_back(*term);
                         products.terms.back().coefficient *= rTerm->coefficient;
                         products.terms.back().exponent    += rTerm->exponent;
                    }
               }
               terms.clear();      // remove all terms from this polynomial
               *this += products;  // uses += because the way += works will combine terms
                                   // with the same exponent
               return *this;
          }
          Polynomial operator+( const Polynomial& rhs ) {
               return Polynomial(*this) += rhs;
          }
          Polynomial operator-( const Polynomial& rhs ) {
               return Polynomial(*this) -= rhs;
          }
          Polynomial operator*( const Polynomial& rhs ) {
               return Polynomial(*this) *= rhs;
          }
          Polynomial operator=( const Polynomial& rhs ) {
               terms = rhs.terms;
               return *this;
          }
     private:
          void printTerm(const size_t term) const {
               // printTerm is of no use aside from as a utility of
               // the printPolynomial public function
               std::cout << terms[term].coefficient << 'x';
               if ( terms[term].exponent > 1) {
                    std::cout << '^' << terms[term].exponent;
               }
          }
          std::vector<Monomial> terms;
};
     
} // end of namespace Doug

#endif