【问题标题】:member operators not working会员运营商不工作
【发布时间】:2016-12-06 05:19:52
【问题描述】:

我创建了一个命名空间,并在该命名空间内创建了一个类。该类称为多项式。我创建了公共成员运算符来执行多项式对象之间的算术运算。但是,当我尝试在 main 中使用它们时,它们并没有给出正确的输出。

我不确定我的错误是在定义上还是在使用它们的方式上。

这是我正在处理的文件的一部分:

标题 |多项式.h

#ifndef _POLYNOMIAL_H_
#define _POLYNOMIAL_H_
//...
namespace algebra {
  class polynomial {
    std::vector<double> coeffStorage;
   public:
    //...
    double operator()(double x);
    polynomial operator+(polynomial p);
    polynomial& operator+=(polynomial p);
    polynomial operator-();
    polynomial operator-(polynomial p);
    polynomial& operator-=(polynomial p);
    polynomial operator*(polynomial p);
    polynomial& operator*=(polynomial p);
  };

polynomial operator+(double c, polynomial p);
polynomial operator*(double c, polynomial p);
//...
}

#endif

cpp |多项式.cpp

//...
//evaluates the polynomial at x
double algebra::polynomial::operator()(double x) {
  double result = 0;

 for (int i = 0; i < size(); i++)
   result += std::pow(x, i) * getCoeff(i);

  return result;
}

algebra::polynomial algebra::polynomial::operator+(algebra::polynomial p) {
  algebra::polynomial result;

  result.resize(degree() + p.degree() + 1);

  for (int i = 0; i < result.size(); i++)
    result.setCoeff(i, (getCoeff(i) + p.getCoeff(i)));

  return result;
}

algebra::polynomial& algebra::polynomial::operator+=(algebra::polynomial p) {
  return ((*this) = (*this) + p);
}

algebra::polynomial algebra::polynomial::operator-() {
  algebra::polynomial result;

  for (int i = 0; i < size(); i++)
    result.setCoeff(i, -1 * getCoeff(i));

  return result;
}

algebra::polynomial algebra::polynomial::operator-(algebra::polynomial p) {
  return ((*this) + -p);
}

algebra::polynomial& algebra::polynomial::operator-=(algebra::polynomial p) {
  return ((*this) = (*this) - p);
}

algebra::polynomial algebra::polynomial::operator*(algebra::polynomial p) {
  algebra::polynomial result;
  double coeffSum = 0.0;

  result.resize(degree() + p.degree() + 1);

  for (int i = 0; i < result.size(); i++) {
    coeffSum = 0;
    for (int j = 0; j <= i; j++) {
      coeffSum = getCoeff(j) * p.getCoeff(i - j);
    }
    result.setCoeff(i, coeffSum);
  }
  return result;
}

algebra::polynomial& algebra::polynomial::operator*=(algebra::polynomial p) {
  return ((*this) = (*this) * p);
}

algebra::polynomial algebra::operator+(double c, polynomial p) {
  algebra::polynomial result = p;

  result.setCoeff(0, c + p.getCoeff(0));

  return result;
}

algebra::polynomial algebra::operator*(double c, polynomial p) {
  algebra::polynomial result = p;

  for (int i = 0; i < result.size(); i++)
    result.setCoeff(i, c * p.getCoeff(i));

  return result;
}
//...

多项式的系数存储在向量中。每个索引都属于多项式的次数。例如,2x^2 + 3 看起来像 3*x^0 + 0*x^1 + 2*x^2,它在向量上存储为 {3.0, 0.0, 2.0}。

我打算在 main 中使用如下操作符:

algebra::polynomial p2;
  p2.setCoeff(0, 1);
  p2.setCoeff(1, 1);
  algebra::polynomial p3;
  p3.setCoeff(0, -1);
  p3.setCoeff(1, 1);

  algebra::polynomial px;
  px = p2 + p3;

  algebra::polynomial py;
  py = p3 * p2;

但是 px 和 py 原来是空的。

【问题讨论】:

标签: c++


【解决方案1】:

正如 cmets 中提到的,没有完整的示例很难确定失败的地方,因为我们不知道这些方法到底在做什么:degree()getCoeff(i)setCoeff(i, c)resize(sz) 但我会尝试:

如果我假设:

  • degree() 在您的示例中的两个多项式中都返回 1,
  • resize(n) 只是调用std::vector::resize 方法,
  • size() 只是调用 std::vector::size 方法
  • getCoeff(i)setCoeff(i, c) 获取和更改 i-esim 向量元素;

那么这两个运算符(+和*)的逻辑都是错误的:

  • 在运算符 + 中,向量被调整为 3,并且循环获取两个输入向量的 3 个元素(但它们都只有 2 个元素!)。调整大小必须使用更大的度数 +1。
  • 在运算符 * 中,向量的大小也被调整为 3(这很好),但获取多项式乘法的循环逻辑是错误的,得到向量中不存在的元素(例如,请参阅 i=2 和 @ 987654334@:p.getCoeff(i-j) == p.getCoeff(2).

除此之外,您可以在自己的类中使用 std::vector::operator[]std::vector::resize 代替 getCoeffsetCoeffresize 方法(即使因为 polynomial::resize 应该是私有的,它也没有从课外调整多项式的大小对我来说没有意义)。

修正的方法是:

algebra::polynomial algebra::polynomial::operator+(algebra::polynomial p) {
    algebra::polynomial result;
    int maxDegree = std::max(p.degree(), degree());
    result.coeffStorage.resize(maxDegree + 1, 0.0);
    for (int i = 0; i <= maxDegree; i++) {
        double value = (i <= degree() ? coeffStorage[i] : 0)
                + (i <= p.degree() ? p.coeffStorage[i] : 0);
        result.coeffStorage[i] = value;
    }
    return result;
}

algebra::polynomial algebra::polynomial::operator*(algebra::polynomial p) {
    algebra::polynomial result;
    int resultDegree = degree() + p.degree();
    result.coeffStorage.resize(resultDegree + 1, 0.0);
    for (int i = 0; i <= degree(); i++) {
        for (int j = 0; j <= p.degree(); j++) {
            result.coeffStorage[i + j] += coeffStorage[i] * p.coeffStorage[j];
        }
    }
    return result;
}

现在,在多项式运算中,有些系数可能为零,如果发生在具有更大幂的那个,则度数减小,因此必须计算方法degree(),不一定是size()-1。比如:

int algebra::polynomial::degree() const {
    int d = std::max(0u, coeffStorage.size() - 1); 
    while(d > 0 && coeffStorage[d] == 0.0)
        d--;
    return d;
}

获取或设置系数的更短/更好的方法可能是使用 operator[] 而不是像这样的 getCoeffsetCoeff(如果您也添加上限验证可能会更好):

double &algebra::polynomial::operator[](size_t i) {
    if (i + 1 > coeffStorage.size())
        coeffStorage.resize(i + 1, 0.0);
    return coeffStorage[i];
}

最后,要打印结果,最好使用以下方法进行人类可读的打印:

std::string algebra::polynomial::str() const {
    std::stringstream ss;
    for (int d = degree(), i = d; i >= 0; i--) {
        double c = coeffStorage[i];
        if (c != 0) {
            if (!std::signbit(c) && i < d)
                ss << '+';
            if (i == 0 || c != 1.0)
                ss << c;
            if (i > 0)
                ss << "y"; // "x" can be confused with "*"?
            if (i > 1)
                ss << i;
        }
    }
    return ss.str();
}

这些方法允许我们进行这样的测试:

int main() {
    algebra::polynomial pa, pb;
    // 4a² + 2a + 3
    pa[2] = 4; pa[1] = 2; pa[0] = 3;
    // 5a³ + 2
    pb[3] = 5; pb[0] = 2;
    std::cout << "pa = " << pa.str() << ", " << "pb = " << pb.str() << std::endl;
    std::cout << "pa + pb = " << (pa + pb).str() << std::endl;
    std::cout << "pa * pb = " << (pa * pb).str() << std::endl;

    return 0;
}

哪个控制台输出是:

pa = 4y2+2y+3, pb = 5y3+2
pa + pb = 5y3+4y2+2y+5
pa * pb = 20y5+10y4+15y3+8y2+4y+6

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-21
    • 1970-01-01
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 2017-02-12
    相关资源
    最近更新 更多