表示多项式的 C++ 模板

c++ templates to represent polynomials

我正在尝试使用模板来表示简单的多项式,如 x^2 + 3x + 5。我的想法是将它们表示为项的总和,每个项都有一个系数和一个幂,例如x^2 有 coeff=1 和 power=2。我还希望能够计算一些 x 的多项式(它们只有 1 个未知但在很多地方)。到目前为止我有:

struct PolyEnd{
    double eval(double x){
        return 0;
    }
};

template <int coeff, int power, class Tail> struct Poly {
    typedef Tail tt;

    double eval(double x){
        double curr = coeff * std::pow(x, power);
        return curr; // has to call eval(x) on rest of the terms which are in the tail and return the sum with "curr"
    }
};

int main()
{
    double x = 2;
    Poly<1,1,Poly<1,1,PolyEnd>> poly;
    std::cout << poly.eval(x) << std::endl;

    return 0;
}

然而,我卡住了。我正在尝试的是可能的吗?如果是这样,我怎样才能使递归 eval() 调用起作用?

是的,你可以这样做,你只需要在尾部调用 eval 并且由于所有 类 都是无状态的,你可以创建一个实例来调用成员函数在现场:

struct PolyEnd{
    double eval(double x){
        return 0;
    }
};

template <int coeff, int power, class Tail> struct Poly {
    typedef Tail tt;

    double eval(double x){
        double curr = coeff * std::pow(x, power);
        return curr + Tail{}.eval(x);
    }
};

int main()
{
    double x = 2;
    Poly<1,1,Poly<1,1,PolyEnd>> poly;
    std::cout << poly.eval(x) << std::endl;

    return 0;
}

或者如果你做evalstatic,那么你可以直接调用Tail::eval(x)

多项式系数可以存储在std::arraystd::vector中(如果您在运行时定义多项式次数)。

然后使用 eval 函数扩展功能。

template <unsigned N>
class Poly : public std::array<double, N> {
public:
  template <typename... E>
  Poly(E &&... e) : std::array<double, N>{{std::forward<E>(e)...}} {}

  double eval(double x) {
    double result = 0;
    double exp = 1.;
    for (auto it = this->rbegin(); it != this->rend(); ++it) {
      result += exp * (*it);
      exp *= x;
    }
    return result;
  }
};

用法

double result = Poly<3>{3., 2., 1.}.eval(17);

我猜您正在试验 元编程。你的问题也让我很兴奋,因为我也是元编程新手,想实践一下。 @walnut 的回答已经被接受,但是分享另一个实现没有坏处。我使用了一些基本的元编程技术。

希望对你有所帮助

#include <cmath>
#include <iostream>
#include <string>

template<int Value>
struct coeff
{   };

template<int Value>
struct power
{   };

template<typename Coefficient, typename Power>
struct term;

template<int Coefficient , int Power>
struct term< coeff<Coefficient> , power<Power> >
{
    inline double eval( double  x ) const noexcept { 
        return Coefficient * std::pow( x , Power );
    }
};

template<int Value>
using constant = term< coeff<Value> , power<1> >;

template<int Value>
using exponential = term< coeff<1> , power<Value> >;

template<typename... T>
struct polynomial
{

    static_assert( sizeof...(T) == 0, "A polynomial can only be expressed in 'term's.");

    [[nodiscard]] constexpr double eval( double ) const noexcept {
        return 0;
    }

    [[nodiscard]] std::string to_string() const noexcept {
        return std::string{};
    }
};

template<int Coefficient, int Power, typename... Tail>
struct polynomial<term< coeff<Coefficient> , power<Power> >, Tail...>
       :   polynomial<Tail...>
{
    [[nodiscard]] constexpr double eval( double x ) const noexcept {
        return m_t.eval( x ) + polynomial<Tail...>::eval( x );
    }

    [[nodiscard]] std::string to_string(){
        using namespace std;
        using namespace std::string_literals;
        return "("s + std::to_string( Coefficient ) + 
               string { "x^" } +
               std::to_string( Power ) + ( sizeof...(Tail) == 0 ? ")" : ") + " ) + 
               polynomial<Tail...>::to_string();
    }

    private:

        term< coeff<Coefficient> , power<Power> > m_t;

};

int main()
{
    auto p1 = polynomial<term< coeff<1> , power<2> > ,
                         term< coeff<2> , power<4> > ,
                         term< coeff<2> , power<3> > ,
                         constant<3> ,
                         exponential<2> >{};

    std::cout << "Polynomial is : " << p1.to_string() << std::endl;
    std::cout << "f(2) : " << p1.eval( 2 ) << std::endl;
    std::cout << "f(3) : " << p1.eval( 3 ) << std::endl;
    return 0;
}

run online