C++ C++;:newton-raphson与重载函数
我编写了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 =
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编译器,
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 );