C++ C++;:newton-raphson与重载函数

C++ C++;:newton-raphson与重载函数,c++,function,iteration,newtons-method,C++,Function,Iteration,Newtons Method,我编写了newton raphson寻根算法的一个简单实现,它将初始猜测init、一元函数f和容差tol作为参数,如下所示: bool newton_raphson(double& init, double(*f)(double), double tol){ const int max_iter = 10000; double next_x, soln = init; int i =

我编写了newton raphson寻根算法的一个简单实现,它将初始猜测
init
、一元函数
f
和容差
tol
作为参数,如下所示:

bool newton_raphson(double& init,
                    double(*f)(double),
                    double tol){
    const int max_iter = 10000;
    double next_x, soln = init;
    int i = 0;

    while(++i < max_iter){
        next_x = soln - f(soln)/fp_x(f, soln);
        if(fabs(next_x - soln) < tol){
            init = next_x;
            return true;
        }
        soln = next_x;
    }
    return false;
}

double fp_x(double(*f)(double),
            double x){
    const double h = 0.000001;
    return (f(x + h) - f(x - h))/2.0/h;
}
然后我的实现工作。但是,我也希望它适用于具有任何给定数量参数的任何函数,但只有第一个参数是可变的。如果我有一个函数f(x,y)=3x+2y

double f(double x, double y){
    return (3*x + 2*y);
}
我想找到使用相同函数的f(x,2)或f(x,3)的根,依此类推n个参数,而不仅仅是一个或两个(请忽略我在示例中展示的函数是简单线性函数的想法,这只是一个示例)。有没有办法为不同数量的参数实现函数,或者我必须为每种情况编写一个实现

谢谢

注意

正如你现在所知道的,这个问题并不是关于newton raphson的,但是如果我把它作为实际问题的一个例子,它会使问题变得更简单,因为它是一个针对不同数量参数函数的单一实现

更新


下面的一些答案使用
std::bind
std::function
来解决问题,这实际上比所选答案更好地解决了我的问题;但是,它们是C++ 11库类库/函数,(这不是我错了,是我强烈要求每个C++程序员继续学习的),在写这篇文章的时候,我正面临着使用它们的一些问题;使用g++4.7(符合c++11)的Eclipse Juno仍然不知何故无法识别
std::function
,因此我决定继续使用下面的检查答案,这也很有效。

我认为您要求的是可变函数:

变量函数–以参数列表结尾声明的函数 使用省略号(…)–可以接受不同数量的 不同的类型。变量函数是灵活的,但它们也是灵活的 危险的编译器无法验证对变量的给定调用 函数传递适当数量的参数或 参数具有适当的类型。因此,对 传递不适当参数的变量函数会产生未定义的变量 行为可以利用这种未定义的行为来运行任意 密码 从这里开始:

然而,如上所述,它们存在一些问题

最值得注意的是,它只适用于编译时

但是,如果您有兴趣实现一个,下面是一篇文章,其中有一个很好的示例:

更新:

在我看来,我认为最好定义接受结构或对象参数的函数(即通用函数对象),然后编写显式处理这些参数的函数


另一种选择是执行一些编译时操作——这会很有用,但在这样的示例中,这样做太麻烦了。另外,C++中的“反射”不是“真”的反射,而是一种“坏”和“强”>不完全<强> >。 变量函数–以参数列表结尾声明的函数 使用省略号(…)–可以接受不同数量的 不同的类型。变量函数是灵活的,但它们也是灵活的 危险的编译器无法验证对变量的给定调用 函数传递适当数量的参数或 参数具有适当的类型。因此,对 传递不适当参数的变量函数会产生未定义的变量 行为可以利用这种未定义的行为来运行任意 密码 从这里开始:

然而,如上所述,它们存在一些问题

最值得注意的是,它只适用于编译时

但是,如果您有兴趣实现一个,下面是一篇文章,其中有一个很好的示例:

更新:

在我看来,我认为最好定义接受结构或对象参数的函数(即通用函数对象),然后编写显式处理这些参数的函数


另一种选择是执行一些编译时操作——这会很有用,但在这样的示例中,这样做太麻烦了。另外,C++中的“反射”不是“真”的反射,而是一个“坏”和“强”>不完全<强>实现。< / P > < P>对于您在这里所做的,您正在寻找的是“代码> STD::BIN < /Cl>”(或者,如果您处理的是C++ 03编译器, STD::BIDN1 < /Cl>和<代码> STD::BND2)。 这些将允许您将值“绑定”到其他参数,从而只需要一个参数的函数(从技术上讲,是一个函数对象)

理想情况下,您希望的是:

double f(double x, double y) { 
     return 3*x + 2*y;
}

double init = 1.0;

newton_raphson(init, std::bind2nd(f, 3), 1e-4);
不幸的是,在实际使用中,它并没有那么简单——要使用
std::bind2nd
,您不能使用实际的函数;您需要使用函数对象,它必须从
std::binary\u函数
派生


std::bind
非常灵活,因此您几乎肯定会使用它(如果可能的话)。

对于您在这里尝试做的事情,您需要的是
std::bind
(或者,如果您使用的是C++03编译器,
std::bind1st
std::bnd2nd

这些将允许您将值“绑定”到其他参数,从而只需要一个参数的函数(从技术上讲,是一个函数对象)

理想情况下,您希望的是:

double f(double x, double y) { 
     return 3*x + 2*y;
}

double init = 1.0;

newton_raphson(init, std::bind2nd(f, 3), 1e-4);
不幸的是,在实际使用中,它并没有那么简单——要使用
std::bind2nd
,您不能使用实际的函数;您需要使用函数对象,它必须从
std::b派生
#include <functional>

bool newton_raphson(double& init,
                    std::function<double(double)>& f,
                    double tol){
    const int max_iter = 10000;
    double next_x, soln = init;
    int i = 0;

    while(++i < max_iter){
        next_x = soln - f(soln)/fp_x(f, soln);
        if(fabs(next_x - soln) < tol){
            init = next_x;
            return true;
        }
        soln = next_x;
    }
    return false;
}

double myfunction(double x, double y){
    return (3*x + 2*y);
}
double fp_x(std::function<double(double)> f, double x) {
    ...
}
...
double d = 1.0;
// Here we set y=2.5 and we tell bind that 1st parameter is unbounded
// If we wanted to switch and set x=2.5 and let y be unbounded, then
// we would use  (&myfunction, 2.5, std::placeholders::_1)
newton_raphson(d, std::bind(&myfunction, std::placeholders::_1, 2.5) , 1e-6);
...
template< typename... Ts >
double f( Ts... Vs ) {
    double array[] = { Vs... };
    int numArg = sizeof...( Vs );
    switch (numArg) {
    case 1:
        return 3 * array[0] + 2;
    case 2:
        return 3 * array[0] + 2 * array[1];
    case 3:
        return 3 * array[0] + 2 * array[1] + 1 * array[3];
    ....
    default:
        return 0.0;
    }
}

template< typename... Ts >
double newton_raphson( double &init, double tol,
                       double (*func) ( Ts... Vs ), Ts... Vs ) {
    return func( Vs... );
}
newton_raphson( &init, 1.0, f, 1.0, 2.0, 3.0, 4.0, 5.0 );