一元仿函数可以有成员变量吗?

Posted

技术标签:

【中文标题】一元仿函数可以有成员变量吗?【英文标题】:Can a unary functor have member variables? 【发布时间】:2014-02-06 23:39:57 【问题描述】:

我想使用两个 boost 库来执行一项任务,但我不确定如何继续。

我有一个函数的代码行,它给了我一个给定 N、x 和 B 值的答案:

double ans = cdf(boost::math::binomial mybinom(N, x), B);

让我们将其表示为 ans = f(B,N,x)。

我想找到它的根,即 x 的值,函数例如y = f(x),结果 y = 0。

我的代码,形式为 y = f(B,N,x) 涉及一个小的重新排列来否定 ans:

double myfun = function(B, N, x, ans)
    double output = (cdf(boost::math::binomial mybinom(N, x), B) - ans);
    return output;

到目前为止一切顺利。现在我在 Boost 中知道根标头中的算法将帮助我们找到根,因此在阅读时我看到 TOMS 算法 748 将接受一元函子作为它的主要参数“f”。下面是一个例子:

#include <iostream>
#include <sstream>
#include <string>


#include <boost/math/tools/roots.hpp>

class Test 
public:
    double operator()(const double x) 
        return x * cos(x);
    
;

// see: 
// http://www.boost.org/doc/libs/1_47_0/libs/math/doc/sf_and_dist/html/math_toolkit/toolkit/internals1/roots2.html

int main(int argc, char** argv) 
    Test t;
    typedef std::pair<double, double> Result;
    boost::uintmax_t max_iter=500;
    boost::math::tools::eps_tolerance<double> tol(30);

    Result r1 = boost::math::tools::toms748_solve(t, 1.0, 2.0, tol, max_iter);
    std::cout << "root bracketed: [ " << r1.first << " , " << r1.second <<  " ]" << std::endl;
    std::cout << "f("<< r1.first << ")=" << t(r1.first) << std::endl;
    std::cout << "f("<< r1.second << ")=" << t(r1.second) << std::endl;
    std::cout << "max_iter=" << max_iter << std::endl;
    return 0;

好的,现在我遇到了一个问题。我看到的每个例子(对于这个和类似的算法)都需要一个一元函子。并显示一个只有 x 作为参数的函数,例如x * cos(x)。然而你看到我的函数有参数 B、N、x 和 ans。那么我如何从 f(B,N,x,ans) 得到一个一元函子,即 f(x),以便提升算法可以接受它作为输入来找到根?

我想到的一件事可能是(我在这里不知道,因为直到现在我才听说过一元仿函数),据我所知,一元仿函数是类,类可以有函数和变量,所以可以设计一个一元仿函数类,所以在创建时,你提供B和N和ans,其值是成员变量,然后一元仿函数的double operator()(const double x)内的函数可以利用B和N和ans因为它们是成员变量,不需要在运算符中提供,因此是一元的。所以就我而言,我在创建对象时指定了 B 和 N 变量,但就 boost 算法和一元运算符而言,它们是成员变量,并且只是函数体内已经可用的值?

我想像这样:

class Test 
public:
    double operator()(const double x) 
        return (cdf(boost::math::binomial mybinom(N, x), B) - ans);
    
private:
    int B;
    int N;
    double ans;
;

我是在正确的路线上还是我在叫错树?

--编辑--

这是我目前为尝试解决此问题而生成的代码:

#include <iostream>
#include <boost/math/distributions/binomial.hpp>
#include <boost/math/tools/roots.hpp>



class MyBinom

    public:
        MyBinom(int n, int b, double p);
        double operator()(const double x);

    private:
        int N;
        int B;
        double P;
;


MyBinom::MyBinom(int n, int b, double p)
            : N(n), B(b), P(p)
        /* Body intentionally empty */


double MyBinom::operator()(const double x)

    boost::math::binomial myBinomial(N, x);
    return (cdf(myBinomial, B) - P);




int main()

    MyBinom myBinom95(4715, 75, 0.95); // Create the Class with the unary operator.

    boost::uintmax_t max_iter=500; // Set max iterations.

    boost::math::tools::eps_tolerance<double> tol(30); //Set the eps tolerance.

    std::pair<double, double> r1 = boost::math::tools::toms748_solve(myBinom95, 0, 1, tol, max_iter); // use the toms solve algorithm.

    std::cout << "Let's take a look at the root" << std::endl;
    std::cout << "root bracketed: [ " << r1.first << " , " << r1.second <<  " ]" << std::endl;
    std::cout << "f("<< r1.first << ")=" << myBinom95(r1.first) << std::endl;
    std::cout << "f("<< r1.second << ")=" << myBinom95(r1.second) << std::endl;
    std::cout << "max_iter=" << max_iter << std::endl;

    return 0;

但是它不能编译 - 与 boost 标头有关:

$ g++ main.cpp -o test
In file included from /usr/include/boost/math/tools/roots.hpp:32:0,
                 from /usr/include/boost/math/special_functions/detail/igamma_inverse.hpp:16,
                 from /usr/include/boost/math/special_functions/gamma.hpp:1528,
                 from /usr/include/boost/math/special_functions/beta.hpp:15,
                 from /usr/include/boost/math/distributions/binomial.hpp:83,
                 from main.cpp:2:
/usr/include/boost/math/tools/toms748_solve.hpp: In function 'std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&, const Policy&) [with F = MyBinom, T = int, Tol = boost::math::tools::eps_tolerance<double>, Policy = boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy>, uintmax_t = long unsigned int]':
/usr/include/boost/math/tools/toms748_solve.hpp:475:71:   instantiated from 'std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&) [with F = MyBinom, T = int, Tol = boost::math::tools::eps_tolerance<double>, uintmax_t = long unsigned int]'
main.cpp:41:100:   instantiated from here
/usr/include/boost/math/tools/toms748_solve.hpp:467:81: error: no matching function for call to 'toms748_solve(MyBinom&, const int&, const int&, double, double, boost::math::tools::eps_tolerance<double>&, uintmax_t&, const boost::math::policies::policy<boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy, boost::math::policies::default_policy>&)'
/usr/include/boost/math/tools/toms748_solve.hpp:467:81: note: candidates are:
/usr/include/boost/math/tools/toms748_solve.hpp:283:17: note: template<class F, class T, class Tol, class Policy> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, const T&, const T&, Tol, uintmax_t&, const Policy&)
/usr/include/boost/math/tools/toms748_solve.hpp:458:24: note: template<class F, class T, class Tol> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, const T&, const T&, Tol, uintmax_t&)
/usr/include/boost/math/tools/toms748_solve.hpp:464:24: note: template<class F, class T, class Tol, class Policy> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&, const Policy&)
/usr/include/boost/math/tools/toms748_solve.hpp:473:24: note: template<class F, class T, class Tol> std::pair<T, T> boost::math::tools::toms748_solve(F, const T&, const T&, Tol, uintmax_t&)

谢谢, 本。

【问题讨论】:

如果你正在做我认为你正在做的事情,你想要一个基于类的操纵器和一个重载的流插入运算符,而不是一元仿函数。 (诚​​然,你可能没有做我认为的那样)。您还可以在 Test 的构造函数中提供您的 N 和 B 并继续使用您现有的表单(这与我第一次提到的非常接近)。 你的想法是完全有效的,一元函子要求它必须可以用单个参数调用,不管它是一个函数指针还是一个包含变量和重载的对象operator() 【参考方案1】:

以下是正确的:

class Test 
public:
    Test(int B, int N, int ans) : B(B), N(N), ans(ans) 

    double operator()(const double x) const 
        return (cdf(boost::math::binomial mybinom(N, x), B) - ans);
    
private:
    int B;
    int N;
    double ans;
;

请注意,大多数情况下,仿函数是被复制的,所以如果你想检索一些“可变”信息(比如你的仿函数被调用了多少次),你必须传递一个额外的指针(一个简单的计数器是不够的) .

【讨论】:

嗨,谢谢,这与我所做的类似 - 我已经用我目前所做的代码更新了原始问题。

以上是关于一元仿函数可以有成员变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

C++结构可以有成员函数吗?

Servlet和Struts2的线程安全问题

Java中类变量可以被继承吗

让成员变量保留而不是分配是更好的做法吗

c语言如何对结构体某一成员初始化

错误回复:私有成员的继承?