2

以下に示すように、初期推定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ますが、1つのパラメーターを除くすべてが定数値を持ちます。明確にするために:以下に示すように、関数f(x)= 3x+2がある場合

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

その後、私の実装は機能します。ただし、任意の数の引数を持つすべての関数で機能するようにしたいのですが、最初の引数のみが可変です。したがって、関数f(x、y)= 3x+2yがある場合

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

同じ関数を使用してf(x、2)またはf(x、3)のルートを見つけたいのですが、1つまたは2つだけでなく、n個の引数についても同様です(例は単純な線形関数です。これは単なる例です)。さまざまな数の引数に対して関数を実装する方法はありますか、それともすべての場合に実装を作成する必要がありますか?

ありがとう、

NAX

ノート

これまでにわかるように、この質問は実際にはニュートンラプソンに関するものではありませんが、引数の数が異なる関数の単一の実装である実際の質問の例として使用すると簡単になります。

アップデート

以下のいくつかの回答は、問題を解決するために使用std::bindstd::functionます。これは、選択した回答よりも実際に私の質問にうまく対処します。ただし、これらはc ++ 11ライブラリのクラス/関数であり(誤解しないでください。これは、すべてのc ++プログラマーに先に進んで学習することを強くお勧めします)、この記事の執筆時点では、いくつかの問題に直面していました。それらを使用する; g ++ 4.7(c ++ 11準拠)を使用するEclipse Junoは、まだ何らかの理由で認識できなかったためstd::function、以下のチェック済みの回答を使用することにしました。これもうまく機能します。

4

4 に答える 4

2

可変個引数関数を求めていると思います。

可変個引数関数(省略記号(...)で終わるパラメーターリストで宣言された関数)は、さまざまなタイプのさまざまな数の引数を受け入れることができます。可変個引数関数は柔軟性がありますが、危険でもあります。コンパイラは、可変個引数関数への特定の呼び出しが適切な数の引数を渡すこと、またはそれらの引数が適切な型を持っていることを確認できません。その結果、不適切な引数を渡す可変個引数関数へのランタイム呼び出しは、未定義の動作をもたらします。このような未定義の動作は、任意のコードを実行するために悪用される可能性があります。ここから:

https://www.securecoding.cert.org/confluence/display/cplusplus/DCL31-CPP.+Do+not+define+variadic+functions

ただし、上で引用したように、それらには多くの問題があります。

最も注目すべきは、コンパイル時のみ機能することです。

ただし、実装に興味がある場合は、次のような良い例の記事をご覧ください。

http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=138

アップデート:

IMO、構造体またはオブジェクトの引数を取る関数(つまり、一般的な関数オブジェクト)を定義し、それらの引数を明示的に処理する関数を作成する方がよいと思います。

もう1つのオプションは、コンパイル時のリフレクションを実行することです。これは便利ですが、このような例では実行するのが面倒です。さらに、C ++の「リフレクション」は「真の」リフレクションではなく、悪い実装であり、不完全な実装です。

于 2013-03-18T04:49:11.123 に答える
2

ここで何をしようとしているのか、探しているのは(または、C ++ 03コンパイラをstd::bind扱っている場合は)です。std::bind1ststd::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::binary_function

std::bindはかなり柔軟性があるので、代わりに(可能であれば)ほぼ確実に使用したいものです。

于 2013-03-18T04:50:03.400 に答える
0

私はあなたの質問をC++11可変個引数テンプレートを学ぶように強制する方法として使用しました。これが実際の例です。

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 );
于 2013-03-18T07:42:11.763 に答える
0

std::bindとを使用できますstd::function。タイプstd::function<double(double)>は、doubleを受け取り、doubleを返す汎関数を表します。同様std::function<double(int,int)>に、2 intを取り、doubleを返す汎関数の場合です。

#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);
...
于 2013-03-18T05:02:15.143 に答える