数值积分:使模板函数只接受函数名或使用两个参数调用的函数

Numerical integration: Make template function take either only the function name or the function called with two arguments

本文关键字:函数 调用 参数 两个 数值积分      更新时间:2023-10-16

我是C++的新手,我正在尝试编写/编辑一个代码,该代码使用梯形规则在数字上集成一个函数。只要我只传递函数的名称,这就可以很好地工作。然而,如果我用两个参数传递函数,这显然会失败,因为没有定义"x"(参见代码)
如何更改代码以使其工作?我必须更改类"梯形"中的某些内容还是仅更改函数"积分"中的某个内容?

#include <iostream>
// Integration routine
template<typename Method, typename F, typename Float>
double integrate(F f, Float a, Float b, long steps, Method m)
{
    double s = 0;
    double h = (b-a)/steps;
    for (int i = 0; i < steps; ++i)
    s += m (f, a + h*i, h);
    return h*s;
}
// The method
class trapezium
{
public:
    template<typename F, typename Float>
    double operator()(F f, Float x, Float h) const
    {
        return (f(x) + f(x+h))/2;
    }
};
// Test function
namespace
{
    double ftest1(double x)
    {
        return (x < 1. ? 0. : 1.);
    }
    double ftest2(double x, double amplitude)
    {
        return x < 1. ? 0. : amplitude;
    }
}
int main()
{
    //This works:
    double res1 = integrate(ftest1, 0., 2., 100, trapezium());
    std::cout << "Result 1: " << res1 << std::endl;
    //This cannot work: 
    double amplitude = 5.;
    double res2 = integrate(ftest2(x, amplitude), 0., 2., 100, trapezium());
    std::cout << "Result 2: " << res2 << std::endl;
    return 0;
}

编辑:不幸的是,由于我无法影响的原因,我不得不坚持C++98标准。

您可以使用"函子"来实现这一点。因此,与其定义要传递的函数,不如定义一个重写operator():的类

class func2{
private:
    double amp;
public:
    func2(double amp) : amp(amp) {}
    double operator()(double x){return amp * stepfunction(x);}
};

现在您可以传递func2:的实例

func2 myfunc2(5.0);
double res2 = integrate(myfunc2, 0.0, 2.0, 100.0, trapezium);

integrate需要一个函数作为第一个参数,使用lambda或std::bind:

double res2 = integrate([=](double x) { return ftest2(x, amplitude); }, 0., 2., 100, trapezium());
// Result 2: 5.05