2

コードを更新しました。私がやろうとしているのは、すべてのラグランジュの係数値をポインター d に保持することです (たとえば、L1(x) の場合、d[0] は "x-x2/x1-x2" になります。d 1は (x-x2/ x1-x2)*(x-x3/x1-x3) など

私の問題は

1)dを初期化する方法(d [0] =(zx [i])/(x [k] - x [i])を実行しましたが、「d [0]」は正しくないと思います

2) L_coeff を初期化する方法。(私は L_coeff=new double[0] を使用していますが、それが正しいかどうかはわかりません。

練習問題: 5 つの点 (x = -1、-0.5、0、0.5、および 1) を使用して、y(x)=cos(π x), x ∈−1,1 のラグランジュの多項式近似を見つけます。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>

using namespace std;

const double pi=3.14159265358979323846264338327950288;

// my function
double f(double x){

return (cos(pi*x));

}


//function to compute lagrange polynomial
double lagrange_polynomial(int N,double *x){
//N = degree of polynomial

double z,y;
double *L_coeff=new double [0];//L_coefficients of every Lagrange L_coefficient
double *d;//hold the polynomials values for every Lagrange coefficient
int k,i;
//computations for finding lagrange polynomial
//double sum=0;

for (k=0;k<N+1;k++){
        for ( i=0;i<N+1;i++){
            if (i==0) continue;
            d[0]=(z-x[i])/(x[k]-x[i]);//initialization
            if (i==k) L_coeff[k]=1.0;
            else if (i!=k){
            L_coeff[k]*=d[i];

                      }

           }

cout <<"\nL("<<k<<") = "<<d[i]<<"\t\t\tf(x)= "<<f(x[k])<<endl;
}

}

int main()
{

    double deg,result;
    double *x;


    cout <<"Give the degree of the polynomial :"<<endl;
    cin >>deg;

    for (int i=0;i<deg+1;i++){
    cout <<"\nGive the points of interpolation : "<<endl;
    cin >> x[i];
    }

    cout <<"\nThe Lagrange L_coefficients are: "<<endl;
    result=lagrange_polynomial(deg,x);



    return 0;
}

これはラグランジュ多項式の例です

これは私が行った解決策です

4

3 に答える 3

6

これは宿題のように思われるので、私はあなたに徹底的な答えを与えるつもりはありませんが、むしろあなたを正しい軌道に乗せるように努めます。

  • コンピュータソフトウェアで多項式をどのように表現しますか?3x ^ 3 + 5x ^ 24-のようなシンボリック式としてアーカイブしたい直感的なバージョンは、それ以上の計算には非常に実用的ではありません。
  • 多項式は、その係数を保存(および出力)することによって完全に定義されます。

上記で行っていることは、C ++が代数的な操作を行い、シンボリック変数を使用して製品を単純化することを望んでいます。これは、C++がかなりの労力なしで実行できることではありません。

2つのオプションがあります。

  • 記号操作を実行できる適切な数式処理システムを使用してください(MapleまたはMathematicaがいくつかの例です)
  • C ++に縛られている場合は、多項式の単一係数を計算する方法をもう少し考える必要があります。プログラムの出力は、数値のリストのみにすることができます(もちろん、記号式に従って見栄えの良い文字列としてフォーマットすることもできます)。

これがあなたに始める方法のいくつかのアイデアを与えることを願っています。

編集1

に値を設定することはないため、コードにはまだ未定義の式がありますy。これはprod*=(y-x[i])/(x[k]-x[i])、意味のあるデータを返さない式として残ります。C ++は数字でしか機能せず、現時点では数字でyはありませんが、記号と考えてください。

コードで設定する場合は、たとえば値でラグレンジ近似を評価できます。これにより、(私が今見る限り)正しい関数値が得られますが、関数自体の説明はありません。1y=1

たぶん、最初にペンと一枚の紙を取り、その表現を正確な数学として書き留めてみるべきでしょう。計算したいものを実際に把握してみてください。もしそうなら、多分あなたはここに戻ってあなたの考えを教えてください。これは、そこで何が起こっているのかを理解するのに役立つはずです。

そして、常に覚えておいてください。C++には、記号ではなく数字が必要です。紙の表現に値がわからない記号がある場合は、既知の値から値を計算する方法を見つけるか、この記号を使用して計算する必要をなくす必要があります。

PS:一度に複数の掲示板に同じ質問を投稿するのは良いスタイルとは見なされません...

編集2

ここで、点y=0.3で関数を評価します。これは、多項式を評価する場合の方法です。ただし、あなたが述べたように、あなたは多項式のすべての係数が必要です。

繰り返しますが、私はまだあなたが問題の背後にある数学を理解していなかったと感じています。たぶん私はあなたに小さな例をあげます。ウィキペディアの記事で使用されている表記を使用します。

k=2およびx=-1、1であると仮定します。さらに、簡単にするために、cos-Functionfという名前を付けます。(ラテックスがないと表記はかなり醜くなります...)次に、ラグランジュ多項式は次のように定義されます。

f(x_0) * l_0(x) + f(x_1)*l_1(x)

ここで(単純化を再び象徴的に行うことによって)

l_0(x)= (x - x_1)/(x_0 - x_1) = -1/2 * (x-1) = -1/2 *x  + 1/2
l_1(x)= (x - x_0)/(x_1 - x_0) = 1/2 * (x+1)  = 1/2 * x  + 1/2

つまり、ラグランジュ多項式は

  f(x_0) * (-1/2 *x  + 1/2) + f(x_1) * 1/2 * x  + 1/2
= 1/2 * (f(x_1) - f(x_0)) * x     +     1/2 * (f(x_0) + f(x_1))

したがって、計算する係数は1/2 *(f(x_1)-f(x_0))および1/2 *(f(x_0)+ f(x_1))になります。

あなたの仕事は、私が行った単純化を実行するアルゴリズムを見つけることですが、シンボルは使用しません。l_jの係数を計算する方法を知っていれば、基本的には完了です。これで、対応するfの値を掛けたものを合計することができます。

したがって、さらに細かく分類すると、l_jの商をコンポーネントごとに相互に乗算する方法を見つける必要があります。これがどのように行われるかを理解すれば、ほぼ完了です。

編集3

さて、もう少し曖昧さを減らしましょう。

まず、L_i(x)を計算します。これらは線形関数の単なる積です。前に述べたように、各多項式を係数の配列として表す必要があります。良いスタイルのためstd::vectorに、この配列の代わりに使用します。次に、L_1(x)の係数を保持するデータ構造を次のように定義できます。

std::vector L1 = std::vector(5); 
// Lets assume our polynomial would then have the form 
// L1[0] + L2[1]*x^1 + L2[2]*x^2 + L2[3]*x^3 + L2[4]*x^4

ここで、この多項式を値で埋めたいと思います。

// First we have start with the polynomial 1 (which is of degree 0)
// Therefore set L1 accordingly:
L1[0] = 1;
L1[1] = 0; L1[2] = 0; L1[3] = 0; L1[4] = 0;
// Of course you could do this more elegant (using std::vectors constructor, for example)
for (int i = 0; i < N+1; ++i) {
    if (i==0) continue;  /// For i=0, there will be no polynomial multiplication
    // Otherwise, we have to multiply L1 with the polynomial
    // (x - x[i]) / (x[0] - x[i])
    // First, note that (x[0] - x[i]) ist just a scalar; we will save it:
    double c = (x[0] - x[i]);
    // Now we multiply L_1 first with (x-x[1]). How does this multiplication change our 
    // coefficients? Easy enough: The coefficient of x^1 for example is just
    // L1[0] - L1[1] * x[1]. Other coefficients are done similary. Futhermore, we have
    // to divide by c, which leaves our coefficient as
    // (L1[0] - L1[1] * x[1])/c. Let's apply this to the vector:
    L1[4] = (L1[3] - L1[4] * x[1])/c;
    L1[3] = (L1[2] - L1[3] * x[1])/c;
    L1[2] = (L1[1] - L1[2] * x[1])/c;
    L1[1] = (L1[0] - L1[1] * x[1])/c;
    L1[0] = (      - L1[0] * x[1])/c; 
    // There we are, polynomial updated.
}

もちろん、これはすべてのL_iに対して実行する必要があります。その後、L_iを追加し、関数を乗算する必要があります。それはあなたが理解するためのものです。(私はそこにかなり多くの非効率的なものを作ったことに注意してください、しかしこれがあなたが詳細をよりよく理解するのに役立つことを願っています。)

うまくいけば、これはあなたがどのように進むことができるかについてあなたにいくつかの考えを与えるでしょう。

于 2011-07-09T12:51:29.163 に答える
1

変数yは実際にはコード内の変数ではありませんがP(y)、ラグランジュ近似の変数を表します。

したがって、計算prod*=(y-x[i])/(x[k]-x[i])sum+=prod*f直接ではなく象徴的に理解する必要があります。

シリーズによる近似を定義することで、これを回避できます

c[0] * y^0 + c[1] * y^1 + ...

c[]コード内の配列で表されます。次に、たとえば乗算を実装できます

d = c * (y-x[i])/(x[k]-x[i])

係数ごとのような

d[i] = -c[i]*x[i]/(x[k]-x[i]) + c[i-1]/(x[k]-x[i])

コンポーネントごとに加算と代入を実装する必要があるのと同じ方法です。

結果は常に、変数の系列表現の係数になりますy

于 2011-07-09T12:52:46.980 に答える
0

既存の回答に加えて、いくつかのコメントがあります。

練習問題: 5 つの点 (x = -1、-0.5、0、0.5、および 1) を使用して、y(x)=cos(π x), x ∈ [-1,1] のラグランジュ多項式近似を見つけます。

あなたが最初に行うことmain()は、多項式の次数を求めることです。あなたはそれをすべきではありません。多項式の次数は、制御点の数によって完全に指定されます。この場合、5 つの点 (x i , cos(π x i ))を通過する固有の 4 次ラグランジュ多項式を作成する必要があります。ここで、x iの値は指定された 5 つの点です。

const double pi=3.1415;

この値は、double はおろか、float には適していません。次のようなものを使用する必要がありますconst double pi=3.14159265358979323846264338327950288;

または、いっそのこと、まったく使用piしないでください。指定された x 値に対応する y 値が何であるかを正確に知っている必要があります。cos(-π)、cos(-π/2)、cos(0)、cos(π/2)、cos(π)とは?

于 2011-07-12T13:59:55.623 に答える