【问题标题】:fsolve &fzero in c++ with GSL root findingc++ 中的 fsolve &fzero 与 GSL 根查找
【发布时间】:2014-05-05 11:46:57
【问题描述】:

我在 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 个根。即使你能给我提供简单的例子,我也会很高兴!

一切顺利。

【问题讨论】:

    标签: c++ matlab root gsl


    【解决方案1】:

    您不能将类成员函数转换为 gsl_function without a wrapper。您必须使用全局函数。在这种情况下,如果您无法提供函数的一阶导数,则您链接的the GSL documentation 上显示的第二个示例是使用该库的标准方法(否则请检查第一个示例)。剩下的简化不多了。

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

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

    更新 1:还有O2Scl,它是我所知道的用于 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);
       }
    };
    

    【讨论】:

    • 非常感谢 Vinicius 的回答!很高兴听到包装纸。我将不使用包装器。您能否澄清一下使用库的标准方式?
    • 好吧,标准方法是使用没有类成员函数的 gsl 对吗?.. 然后不,我必须使用它作为我的类函数之一,因为它应该使用预先计算的全局参数。如果我使用 gsl 函数,那么我应该以某种方式将所有参数传递给该函数。在这里,我找到了您的一个解决方案stackoverflow.com/questions/13074756/… 但是这种方式正在推动它非常努力地工作。必须有其他方法。你能告诉我,或者链接我更多关于包装的信息吗?似乎我会编写自己的包装函数,需要建议
    • 非常感谢 Vinicius,你是这个话题上的佼佼者。我明白了,但现在不能尝试。我会让你知道的。非常感谢+++!!!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-04
    • 1970-01-01
    • 1970-01-01
    • 2012-09-09
    • 1970-01-01
    相关资源
    最近更新 更多