3

それで、テイラー近似を使って cos(x) を計算するプログラムを作成しようとしています。

プログラムは非常に単純です。ユーザーはパラメーター x (x はラジアン単位の角度) と float ε (cos(x) の値の精度) を入力します。

基本的に、プログラムがしなければならないことは、この合計を計算することだけです: x^0/0! - x^2/2! + x^4/4! - x^6! + x^8/8! - ...、項が ε よりも小さくなるまで、つまり cos(x) の値は、精度の範囲内になります。

コードは次のとおりです。

#include <stdio.h>

/* Calculates cos(x) by using a Taylor approximation:
   cos(x) = x^0/(0!) - x^2/(2!) + x^4/(4!) - x^6/(6!) + x^8/(8!) - ... */

int main(void)
{    
    int   k;         // dummy variable k

    float x,         // parameter of cos(x), in radians
          epsilon;   // precision of cos(x) (cos = sum ± epsilon)
          sum,       // sum of the terms of the polynomial series
          term;      // variable that stores each term of the summation

    scanf("%f %f", &x, &epsilon);

    sum = term = 1, k = 0;

    while (term >= epsilon && -term <= epsilon) 
    // while abs(term) is smaller than epsilon
    {
        k += 2;
        term *= -(x*x)/(k*(k-1));
        sum += term;
    }

    printf("cos(%f) = %f\n", x, sum);

    return 0;
}

最初は、別の変数 "fact" で階乗を計算して解決しようとしましたが、ε の妥当な大きな値でもオーバーフローが発生しました。

これを解決するには、前の項に -x² / (k(k - 1)) を掛けて、反復ごとに k を 2 ずつ増やして、次の項を取得できることに気付きました。これで問題は解決すると思いましたが、やはりうまくいきません。

プログラムは正常にコンパイルされますが、たとえば、次のように入力した場合:

3.141593 0.001

出力は次のとおりです。

cos(3.141593) = -3.934803

...そしてそれは明らかに間違っています。誰かが私を助けることができますか?

4

2 に答える 2

5

バグはwhileループの状態にあります:

while (term >= epsilon && -term <= epsilon)

正しい状態ではありません。ロジックを修正することで修正できますが、次のようになります。

while (term >= epsilon || -term >= epsilon)

fabsコードの関数をより明確にするため、標準の浮動小数点abs関数を使用する必要があります。

while (fabs(term) >= epsilon)

その変更を適用してプログラムをコンパイルした後、私はそれを使用して計算しましcos(3.141593) = -1.000004た。これは正しいことです。

于 2013-02-21T07:02:25.163 に答える
4

Charliehorse55の答えに追加するだけです。

通常、単純な三角法を使用して引数の削減を行います

cos(x + y) = cos(x)cos(y) - sin(x)sin(y)
sin(x + y) = cos(x)sin(y) + sin(x)cos(y)

引数を [0..SmallAngle] の範囲に減らしてから、テイラー展開を計算します。

于 2013-02-21T09:15:01.967 に答える