使用 GSL 根查找在 C++ 中求解 &fzero

fsolve &fzero in c++ with GSL root finding

本文关键字:fzero C++ GSL 查找 使用      更新时间:2023-10-16

我在Matlab中有一个原型代码,它在一些计算中使用fsolve和fzero。在c++中,我使用GSL并试图找到值x,这是f(x)=0;

对于我的例子,在Matlab我做:

functionSolver= @(x) myFunction(x);
XSol = fsolve(functionSolver,0);

这个显然解决了Matlab函数,它是:

function F = myFunction(x)
%% do something with x
F = x;
end

那么在 c++ 中,我将myFunction设置为;

double myClass::myFunction(double x){
//do something with x
return x;
}

在GSL文档中,它告诉根查找示例,但需要一些帮助。https://www.gnu.org/software/gsl/manual/html_node/Root-Finding-Examples.html Root-Finding-Examples

一定有明确的方法求出给定函数的0个根。即使你能给我一个简单的例子,我也会很高兴的!

所有最好的。

如果没有包装器,就不能将类成员函数强制转换为gsl_function。必须使用全局函数。在这种情况下,您链接的GSL文档中显示的第二个示例是使用库的标准方法,如果您不能提供函数的一阶导数(否则请检查第一个示例)。没有多少简化的余地了。

但是,如果您愿意使用包装器,有许多方法可以简化您的生活。例如,您可以使用包装器来启用c++11的特性,如lambdas!一般来说,我不建议任何人在没有仔细检查代码的情况下为GSL使用第三方包装器。你应该先学习标准的方法。

另一个例子:我开发了一个小包装器,它简化了GSL 1D根查找器API。您可以在这个链接中找到源代码和一个很好的示例。我不是说你应该使用我的包装。随着时间的推移,你可能会发展出自己的!

更新1:还有o2sl,这是我所知道的最发达的gsl c++包装器。它似乎有一个非常好的API。再次强调:您应该非常小心地使用包装器。

更新2:回答评论中提出的一个问题:您也可以创建一个全局函数并将其用作包装器。例子:

double myFunction(double x, void* ptr) {
    myClass* ptr2 = static_cast<myClass*>(ptr);
    return ptr2->myFunction(x);
}

在更复杂的情况下我不喜欢这个解决方案(但这里是完全好的,可能是更简单的选择),因为如果你想发送更多的参数(例如:你需要2个参数:类本身和一个额外的数字-在这种情况下,你需要创建一个额外的结构来容纳这两个!)使用我链接的包装器,您可以使用lambdas轻松发送许多参数!示例

double a = 1;
myClass m1 ....
gsl_function_pp Fp( [&](double x){return a * m1.myFunction(x);} ); 
gsl_function *F = static_cast<gsl_function*>(&Fp); 

为了完成,下面是包装器代码

class gsl_function_pp : public gsl_function
{
   public:
   gsl_function_pp(std::function<double(double)> const& func) : _func(func){
   function=&gsl_function_pp::invoke;
   params=this;
   }     
   private:
   std::function<double(double)> _func;
   static double invoke(double x, void *params) {
   return static_cast<gsl_function_pp*>(params)->_func(x);
   }
};