2017-01-21 3 views
-1

私は簡単に何か...私は推測で働いていますが、私は気になるものがあります。コサインテイラーaproximationのC言語

double x,t,cos_aprox,eps; 
int k; 
t=1.0; 
k=1; 
cos_aprox=1.0;` 

printf("Introduceti x pentru care se calculeaza cos(x) si eroarea epsilon:\n"); 
if(scanf("%lf%lf",&x,&eps)!=2) 
{ 
    printf("Date eronate!!\n"); 
    exit(1); 
} 
else 
{ 
    do 
    { 
     t=t*(-1)*x*x/(k*(k+1)); 
     cos_aprox+=t; 
     k+=2; 

    } 
    while(fabs(t)>eps); 

    printf("Valoarea aproximativa a lui cos(%g) este %.9g. k este %d\n",x,cos_aprox,k); 
    printf("Valoarea lui cos(%g), folosind functia din biblioteca, este %.9g.",x,cos(x)); 
} 

それは良い結果を返しますが、私は39ラジアン上で任意の値を選択すると、それとライブラリ関数cos(x)との間に有意な違いがあります。

任意の推測?テイラー級数の

+2

引数が '[-pi/4、pi/4]'の範囲にある場合にのみ機能します。削減に必要なpiの桁数には大きな整数の計算が必要です。論文:http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.67.5616 – deamentiaemundi

+0

改善のためにwhileループの前に 'x = fmod(x、2 * pi);を使ってください。これは '' x> 1e10'のような大きな '' x ''にはまだ問題があります。あなた自身のコードを使って 'cos()'をどのように広範囲にわたって正確に動作させるかの詳細は、 – chux

答えて

1

OPの使用はxの増加値と数値の制限を受けます。大きな交互符号語の追加は、あまりにも多くの誤差を累積する。これらの用語を見るためにコードを修正してください。

t = t*(-1)*x*x/(k*(k+1)); 
printf("%e\n", t); 

[-2π... +2π]の 範囲引数還元の両方正弦及び余弦計算給付。以下は、良い第一ステップであり、広い範囲xための誤差を低減提供します。

x = fmod(x, 2*π); 

範囲にさらに低減[0 ... +π/ 4]通常の三角恒等式とremquo()を用いて使用することができます。 Degrees example


トラブルは、上記計算はπの近似値に依存しているということです。 π、無理数である、正確doubleとして表すことができません。すべての有限のdoubleは有理数です。だからではなく、機械パイが使用されています。 double x全体範囲にわたり正確な計算を達成するために

// example 
#define M_PI 3.1415926535897932384626433832795 
x = fmod(x, M_PI); 

は、洗練された拡張精度の技術を必要とします。 大きな引数の引数の削減:最後のビットまでは良い