如何编写代码来计算C++中多个变量函数的偏导数?

How to write code to calculate partial derivative of several variable function in C++?

我已经编写了代码来计算单变量函数在某个点的导数,方法是制作一个名为“Der”的 class。在class Der中,我定义了两个私有变量double fdouble df以及一个print()函数来打印fdf的值。在 class 中,我重载了运算符 +, -, *, /, ^ 来计算函数的和、差、乘等的导数。我无法展示整个代码,因为它很长,但我会展示一些片段来提供一个想法。

class Der{
private:
    double f;  // function value at x
    double df; // derivative of function at x
public:
    Der();
    Der(double);
    Der operator+(Der); // f + g
    Der operator-(Der); // f - g
    Der operator*(Der); // f * g
    Der operator/(Der); // f / g
       
    friend Der operator+(double, Der); //c+f
    friend Der operator-(double, Der); //c-f
    friend Der operator*(double, Der); //c*f
    friend Der operator/(double, Der); //c/f
    Der operator^(double); // f^c,  Where c is constant
   
    friend Der sin(Der);
    friend Der cos(Der);
    friend Der tan(Der);
    friend Der log(Der);
    friend Der exp(Der);
    
    void print();
};

Der :: Der(){}

Der :: Der(double x){
    this->f = x;
    this->df = 1;
}

Der Der :: operator+(Der g){
    Der h;
    h.f = this->f + g.f;
    h.df = this->df + g.df;
    return h;
}

Der sin(Der g){
    Der h;
    h.f = sin(g.f);
    h.df = cos(g.f)*g.df;
    return h;
}
void Der :: print(){
    cout<<"Derivative of function at a point : "<<df<<endl;
}

int main()
    {
        Der x(10), f;
        f = x^2+x^3;
        f.print();
    }

现在我想用这个导数计算器来计算一个多变量函数的偏导数,并最终计算出该函数的梯度。我有一些模糊的想法,但我无法在代码中实现它。我是C++编程的初学者,所以如果你不使用太多高级概念,这将对你有所帮助。

如有任何帮助,我们将不胜感激。谢谢!

编辑: 我添加了 Der 的用法。该程序应采用 x(2), y(4), z(5) 等独立变量的输入,并像 f(x,y,z)=x^2*y*z+log(x*y*z) 一样发挥作用。然后,它会以数组的形式给出fw.r.tx, y, z(2, 4, 5)点的偏导数。但是,我只需要一些关于如何编写偏导数计算器代码的想法。

您似乎非常接近解决方案,但在跨多个维度定义函数的步骤上遇到困难。

您需要多个成员变量,而不是一个成员变量 df,每个偏导数一个。你可以 hard-code 他们:

double dfx, dfy, dfz;

或使用容器:

double df[3];

我暂时使用 hard-coding。 (容器是一个非常重要的话题,std::vector 在几乎所有方面都比数组好,但一次只有一件事。)

将另一个变量从 x 重命名为 v 也是明智的,因为它表示函数在点处的 兴趣,而不是点的位置。 (这个值得思考。)

老构造函数取一值一导:

Der :: Der(double x){
    this->f = x;
    this->df = 1;
}

这可以使用初始化器更好地编写:

Der :: Der(double nx): x(nx), df(1)
{}

这使得重写构造函数以采用三个偏导数变得容易:

Der :: Der(double nv, double dx, double dy, double dz): v(nv), dfx(dx), dfy(dy), dfz(dz)
{}

现在我们可以声明函数了:

Der x(2, 1, 0, 0), y(4, 0, 1, 0), z(5, 0, 0, 1);

并且算术运算的逻辑很简单。例如,两个函数乘积的第一部分:

dfx = A.v * B.dfx + A.dfx * B.v;

(事实上,您可以从当前的 class 中抽象出算术,并将其用于旧的和新的 classes,但一次只能做一件事。)