#ifndef POLYNOMIAL_H #define POLYNOMIAL_H #include #include #include #include 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::const_iterator rTerm = rhs.terms.begin(); rTerm != rhs.terms.end(); ++rTerm ) { bool match = false; for ( std::vector::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::const_iterator rTerm = rhs.terms.begin(); rTerm != rhs.terms.end(); ++rTerm ) { bool match = false; for ( std::vector::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::const_iterator rTerm = rhs.terms.begin(); rTerm != rhs.terms.end(); ++rTerm ) { for ( std::vector::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 terms; }; } // end of namespace Doug #endif