2016-10-23 4 views
0

私はmath.hのsin関数であることを知っていますが、私は自分自身でその関数を楽しいものにしたいと考えています。私は正弦関数のMacluarin展開に基づいてsin関数を作成しました。 enter image description herecでサイン関数を作成する方法

私は、電力機能や階乗関数を書き、彼らはint型メインから正常に動作しますが、彼らはここで、sin関数では動作しません。私のコードは

ある
int main() 
{ 
    int i; 
    double y; 
    printf("\n\nPlease enter a value to find corresponding sin value\n"); 
    scanf("%d",&i); 
    y=sin(i); 
    printf("\nYour value is\n %f",y); 
    return 0; 
} 

double sin(int z) 
{ 
    int i=1; 
    double value,val2,val3,sum=0; 
    for(i=1;i<33;i+=2) 
    { 
     val2=power(z,i); 
     val3=factorial(i); 
     value=val2/val3; 
     if(((i-1)/2)%2!=0){ 
      sum=sum-value; //((power(x,i))/factorial(i)); 
     }else 
     { 
      sum=sum+value; 
     } 
    } 
    printf("\n%f\n",sum); 
    return sum; 
} 

int factorial(int x) 
{ 
    int i,sum=1; 
    for(i=1;i<=x;i++) 
    { 
     sum = sum*i; 
    } 
    return sum; 
} 

int power(int x,int y) 
{ 
    unsigned long long int i,sum=1; 
    for(i=1;i<=y;i++) 
    { 
     sum=sum*x; 
    } 
    return sum; 
} 

どれ提案役立ちます。

+0

オーバーフロー以外に、整数を使用すると、小数点以下が切り捨てられます。ああ、あなたはそれらを呼び出す前に関数を宣言していますか? 'main'関数の上に関数プロトタイプがありますか? –

+0

条件if if(((i-1)/ 2)%2!= 0) 'の目的は何ですか? – Raman

+0

@ARBYこれは、sum-x^3/3のような連続した '-'値のためです! – Kumar

答えて

4

数式はラジアン単位の値を期待していますが、整数を使用していますので、あなたはそれを度量すると仮定しています。それは数式に間違った値を与えます。

また、factorial()およびpower()の戻り値としてintを使用すると、オーバーフローが発生します。は2^31-1になり、2^33を得ることができないので、32ビットマシンでも2を与えると数式がオーバーフローします。

また、の戻り値の型を持つ関数からunsigned long long intを返すとコンパイラから通知されない場合は、警告レベルを上げてください。

4

int factorial()は非常に高速にオーバーフローします。 13!が32ビット整数に収まりません。 21!が64ビット整数に収まりません。

int power()は完全にオフのようです。なぜあなたは、引数xintになると思いますか?ところで、それもすぐにオーバーフローします。

McLauren系列を計算する(ほとんど)右の方法は、以前のものから次の用語を表明することにある。

term = (-1) * term * (x*x)/((n+1)*(n+2)); 
    sum += term; 
    n += 2; 

それが動作しなければならないが、大きなxで数値不安定性をもたらし得ます。 A Horner scheduleは究極の答えです。

1

すでに述べたように、powerfactorialの部分は、小さな値でもオーバーフローするため、独自の関数で計算することは悪い考えです。

計算を結合して、各ループにmultiplicationdivideがあるようにすることができます。このよう

#include <stdio.h> 

// This function returns the contribution from the k'th element 
double kth_contribution(double x, int k) 
{ 
    int i; 
    int s = -1.0; 
    double d = 1.0; 
    if (k < 0) return 0; 
    if (k == 1) return x; 
    if (k % 2 == 0) return 0; 
    if ((k-1) % 4 == 0) s = 1.0; 

    for (i=1; i<=k; ++i) 
    { 
     d = d * x/i; 
    } 
    d = s * d; 
    return d; 
} 

int main(void) { 
    int k; 
    int x = 1.0; 
    for (k=0; k<33; ++k) 
    { 
     printf("k=%d: %0.80f\n", k, kth_contribution(1.0, k)); 
    } 
    return 0; 
} 

出力:

k=0: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=1: 1.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=2: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=3: -0.16666666666666665741480812812369549646973609924316406250000000000000000000000000 
k=4: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=5: 0.00833333333333333321768510160154619370587170124053955078125000000000000000000000 
k=6: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=7: -0.00019841269841269841252631711547849135968135669827461242675781250000000000000000 
k=8: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=9: 0.00000275573192239858925109505932704578867742384318262338638305664062500000000000 
k=10: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=11: -0.00000002505210838544172022386617932135366437762513669440522789955139160156250000 
k=12: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=13: 0.00000000016059043836821615925802332523156679827680548555690620560199022293090820 
k=14: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=15: -0.00000000000076471637318198174152558028953378813433183758263567142421379685401917 
k=16: 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000 
k=17: 0.00000000000000281145725434552099254097088490189675684814327692728763707918915316 

.... 

は今、あなたはちょうど一緒にすべての貢献を追加する必要があります。

1

fdlibmのような標準的な数学ライブラリを見ると、それらはすべて引数の削減を行います。 Macluarinシリーズはxの小さな値に最適です。したがって、大きなxの場合、xを小さな範囲にしたいとします。 -pi/2とpi/2の間にyが見つかると、x = y + 2k piのようにラジアンで作業します。または、x = pi-y + 2k pi。

これは、yを小さな範囲にするのに役立ち、計算に必要な系列数が少なくて済むようになります。

関連する問題