0

入力ファイルから多項式を構築するプログラムを作成しようとしています。多項式を読み取り、値をクラス属性「係数」および「指数」に格納します。たとえば、係数 = 2、指数 = 3 は 2x^3 になります。多項式を読み込んで出力するときに処理しなければならない厄介なケースがたくさんあります。( operator<<and operator>>functions) メイン関数は、polynomial.cpp を徹底的にテストします。私の問題の 1 つは多項式の構築にあると思います。お気づきかもしれませんが、派生関数のコードを書くのにも問題があります。ここに私が持っているものがあります:

#ifndef _POLYNOMIAL_H
#define _POLYNOMIAL_H

#include <iostream>
#include <vector>
#include <sstream>

using namespace std;

class Polynomial {

 public:

  Polynomial();
  Polynomial(vector<double> iCoefficients, vector<int> iExponents);

  int Degree() const;
  double Evaluate(double x) const;
  Polynomial Derivative() const;

  friend Polynomial operator+(const Polynomial & p, const Polynomial & p2);
  friend Polynomial operator*(const Polynomial & p, const Polynomial & p2);
  friend ostream& operator<<(ostream& out, const Polynomial & p);
  friend istream& operator>>(istream& in, Polynomial & p);

 private:

  vector<double> coefficients;

};
#endif

#include "polynomial.h"
#include <stdexcept>
#include <vector>
#include <cmath>

using namespace std;

// Default Constructor
Polynomial::Polynomial() { 
  coefficients.push_back(0);
}

// Constructor for a Polynomial
Polynomial::Polynomial(vector<double> iCoefficients, vector<int> iExponents) { 

  for (int i = 0; i < iExponents[0]; i++) {
    coefficients.push_back(0);
  }

  for (size_t i = 0; i < iExponents.size(); i++) {
    coefficients[(Degree() - iExponents[i])] = iCoefficients[i];
   }
 }

// Returns highest exponent of the polynomial
int Polynomial::Degree() const { 

  return coefficients.size();
}

// Evaluates the polynomial at a particular point
double Polynomial::Evaluate(double x) const { 

  double result;

  for(int i = 0; i <= Degree(); i++) {
    result += pow(x, Degree() - i) * coefficients[i];
  }
  return result;
}

// Returns first derivative of the polynomial
Polynomial Polynomial::Derivative() const { //----------------------???

//   Polynomial result;

//   for(int i = 0; i <= Degree(); i++) {
//     result.coefficients[i] = coefficients[i] * (Degree() - i);
//   }
//   return result;
}         


// Returns polynomial object that is the sum of parameters
Polynomial operator+(const Polynomial & p, const Polynomial & p2) { 

  int d = p.Degree();
  int d2 = p2.Degree();
  Polynomial sum;

  for (int j = 0; j < d; j++) {
    for (int i = 0; i < d2; i ++) {
      sum.coefficients.push_back(p.coefficients[j] + p2.coefficients[i]);
    }
  }
  return sum;
}

// Returns polynomial object that is the product of parameters
Polynomial operator*(const Polynomial & p, const Polynomial & p2) {

  int d = p.Degree();
  int d2 = p2.Degree();
  Polynomial product;

  for (int j = 0; j < d; j++) {
    for (int i = 0; i < d2; i ++) {
      product.coefficients.push_back(p.coefficients[j] * p2.coefficients[i]);
    }
  }
  return product;
}

// Output operator
ostream& operator<<(ostream& out, const Polynomial & p) {

  for (int i = 0; i <= p.Degree(); i++) {

    if(i == 0 && p.Degree() <= 1) {
      out << 0;
    }

    if (p.coefficients[i] != 0 && i != 0) {
      out << '+';
    }

    if (p.coefficients[i] != 0) {
      out << p.coefficients[i];
      if(i < (p.Degree() - 1)) {
    out << "x^";
    out << (i - p.Degree()) * (-1);
      }
    }
  }
  return out;
}

// Input operator
istream& operator>>(istream& in, Polynomial & p) {

  char ch;
  int exponent;
  double coefficient;
  vector<double> coefficients;
  vector<int> exponents;

  while(isspace(ch) == false) {

    ch = in.peek();
    if(ch == '+') {
      in.ignore();
      in >> coefficient;
    }
    else if(ch == '-') {
      in.ignore();
      in >> coefficient;
      coefficient = coefficient * (-1);
    }
    else {
      in >> coefficient;
    }
      ch = in.peek();
      if((ch <= 'z') && (ch >= 'a')) {
    in >> ch;
    ch = in.peek();
      if(ch == '^') {
        in.ignore();
        in >> exponent;
      }
      else 
        exponent = 1;
      }
      else
    exponent = 0;

      coefficients.push_back(coefficient);
      exponents.push_back(exponent);
  } 

  p = Polynomial(coefficients, exponents);

  return in;
}

#include <iostream>
#include <sstream>
#include <string>
#include <cmath>
#include "polynomial.h"

using namespace std;

bool testPolynomial(const Polynomial& p, string expected);
bool testOperations(const Polynomial& p, int degree, double expected);
bool testInput(string s);


int main() {
  int errors = 0;

  cerr << "Note: Nearly all of the tests expect a working output operator. If a test fails, check that first" << endl;
  cerr << "Testing default constructor" << endl;
  Polynomial p1;   // test default constructor
  errors += testPolynomial(p1, "0");

  cerr << "Testing explicit value constructor" << endl;
  double c_arr[] =  {1.1, 2, 4, 7};
  int e_arr[] = {6, 3, 2, 0};
  vector<double> c(c_arr, c_arr+4);
  vector<int> e(e_arr, e_arr+4);
  Polynomial p2(c, e);
  errors += testPolynomial(p2, "1.1x^6+2x^3+4x^2+7");
  c.clear(); e.clear();
  cout << '1' << endl;
  Polynomial p3(c, e);
  errors += testPolynomial(p3, "0");
  cout << '2' << endl;

  cerr << "Testing operations" << endl;
  double c2_arr[] =  {-1.1, 2, -4, 7};
  int e2_arr[] = {4, 3, 2, 0};
  vector<double> c2(c2_arr, c2_arr+4);
  vector<int> e2(e2_arr, e2_arr+4);
  Polynomial p4(c2,e2);
  errors += testOperations(p1, 0, 0);
  errors += testOperations(p2, 6, 109.4);
  errors += testOperations(p4, 4, -10.6);

  errors += testPolynomial(p1.Derivative(), "0");
  errors += testPolynomial(p2.Derivative(), "6.6x^5+6x^2+8x");
  errors += testPolynomial(p4.Derivative(), "-4.4x^3+6x^2-8x");

  errors += testPolynomial(p1+p2, "1.1x^6+2x^3+4x^2+7");
  errors += testPolynomial(p2+p4, "1.1x^6-1.1x^4+4x^3+14");

  errors += testPolynomial(p1*p2, "0");
  errors += testPolynomial(p2*p2, "1.21x^12+4.4x^9+8.8x^8+19.4x^6+16x^5+16x^4+28x^3+56x^2+49");
  double c_arr3[] = {-1};
  int e_arr3[] = {0};
  vector<double> c3 = vector<double>(c_arr3, c_arr3+1);
  vector<int> e3 = vector<int>(e_arr3, e_arr3+1);
  Polynomial p5(c3, e3);

  errors += testPolynomial(p2 * p5 + p2, "0");
  errors += testPolynomial(p5, "-1");

  cerr << "Testing input operator." << endl;
  testInput("0");
  testInput("51");
  testInput("-1.1");
  testInput("3x^2");
  testInput("-5x^3-5");
  testInput("x^5+x-1");
  testInput("-x^4+2");

  return errors;
}

bool testPolynomial(const Polynomial& p, string expected) {
  ostringstream out;
  out << p;
  if (out.str() != expected) {
    cerr << "Test failed: expected " << expected << " got " << out.str() << endl;
    return true;
  } else {
    return false;
  }
}

bool testOperations(const Polynomial& p, int degree, double expected) {
  if(p.Degree() != degree) {
    cerr << "Failed Degree operation" << endl;
    return true;
  }
  double result = p.Evaluate(2.0);
  if (fabs(result - expected) > 1e-5) {
    cerr << "Failed Evaluation operation" << endl;
  }
  return false;
}

bool testInput(string s) {
  Polynomial p;
  istringstream in(s+" ");
  in >> p;
  ostringstream out;
  out << p;
  if (out.str() != s) {
    cerr << "Failed input test. Expected: " << s << " got " << out.str() << endl;
    return true;
  }
  return false;
}
4

1 に答える 1

1

このPolynomial::Degree()関数には、オフバイワンのバグがあります。それは戻るべきですsize()-1


係数と指数のリストを変換するには、まず最大指数を見つけます。これは多項式の次数になります。

int degree = *std::max_element(iExponents.begin(), iExponents.end());

次に、この数のゼロで係数を初期化します (プラス 1、上記を参照)。

coefficients.assign(degree + 1, 0);

次に、あなたと同じように各係数を設定します。


ただし、累乗/指数の昇順を使用する方がはるかに優れています! この方法では、常に計​​算する必要はなくDegree()-i、代わりに使用できますi

for (size_t i = 0; i < iExponents.size(); i++) {
    coefficients[iExponents[i]] += iCoefficients[i];
}

+=上記のコードに注意してください。のような多項式を処理3x+4x+5xし、 と同等にし12xます。


あなたの足し算と掛け算のアルゴリズムは完全に間違っています。コンストラクターで行ったように、最初に出力多項式の次数を設定する必要があります。

Polynomial operator+(const Polynomial & p, const Polynomial & p2)
{
    int d = p.Degree();
    int d2 = p2.Degree();
    Polynomial sum;

    sum.coefficients.assign(std::max(d, d2) + 1, 0);
    ...
}

あなたがそれについて考えようとすると、残りは簡単になるはずです。


加算を実行した後、ゼロの最高次数係数をチェックしたい場合があります。たとえば、 と を追加する2x^2+x+1-2x^2+x+1が得られ0x^2+2x+2、これを に変換する必要がある場合があります2x+2

while (coefficients.back() == 0)
    coefficients.resize(coefficients.size() - 1);
if (coefficients.empty())
    coefficients.push_back(0);

導関数は、いったん正しく理解すれば、簡単なはずoperator+ですoperator*

于 2012-11-22T20:21:07.770 に答える