2016-10-04 4 views
1

私はそれぞれのテイラー級数を計算するプログラムを作ったが、教授は最初に分けてそれを変えて欲しい。これは私のコードで、最初の部分にdivide()を使っています。私のpower()とfact()は、私の古いコードへの参照に過ぎません。 テイラー級数をCで割って最初に掛け算すると、

#include <stdio.h> 
#include <math.h> 

int main() 
{ 
double x, mySin(), myCos(), myExp(); 
char more; 

do  { 
    printf ("\n\t\t\t\t\tInput x: "); 
    scanf ("%lf", &x); 
    printf ("\n\t\t\t\t\t\t\tLibraryResult \t MyResult"); 
    printf ("\n\t\t\tSin(%6.2f)\t  %9.6f\t\t%9.6f", x, sin(x), mySin(x)); 
    printf ("\n\t\t\tCos(%6.2f)\t  %9.6f\t\t%9.6f", x, cos(x), myCos(x)); 
    printf ("\n\t\t\tExp(%6.2f)\t  %9.6f\t\t%9.6f", x, exp(x), myExp(x)); 
    printf ("\n\n\t\t\t\t\tDo more (Y/N) ?"); 
    scanf ("%s", &more); 
} while (more == 'y' || more == 'Y'); 
} 

double mySin(double x) 
{ 
double sum = 0., divide(); 
int i, sign = 1; 

for (i = 0; i < 30; i++, sign = - sign) 
    sum = sum + sign * divide(x) ; //power(x, 2 * i + 1)/fact(2 * i + 1); 

return sum; 
} 

double myCos(double x) 
{ 
double sum = 0., divide(); 
int i, sign = 1; 

for (i = 0; i < 30; i++, sign = - sign) 
    sum = sum + sign * divide(x);//power(x, 2 * i)/fact(2 * i); 

return sum; 

} 

double myExp(double x) 
{ 
double sum = 0., divide(); 
int i; 

for (i= 0; i < 30; i++) 
    sum = sum + divide(x); //power(x, i)/fact(i); 


return sum; 
} 


double divide(int n, double x) 
{ 
int i; 
double div = 1.; 

for (i = 1; i < n; i++) 
    div = x/i; 

return div; 

} 

/*double fact(int n) 
{ 
int i; 
double prod = 1.; 

for (i = 1; i <= n; i++) 
    prod = prod * i; 

return prod; 
} 

double power (double x, int n) 
{ 
int i; 
double prod = 1.; 

for (i = 0; i < n; i++) 
    prod = prod * x; 

return prod; 
} 
*/ 

は、私は、Xを入力したとき< nはない結果が得られていない私を使用して、分割のコードとき()をいじりてきました。しかし、私は30を使用しますが、計算は間違っています。私は自分自身でこれを理解しようとしているので、ちょうどポインタが役に立つでしょう!ありがとう!

+0

'divide'関数では、毎回' div'の値を上書きするだけなので 'for'ループは何もしません。したがって、関数は 'return x /(n-1);'と等価です。多分あなたは 'div * = x/i;'を意味していたでしょう。 – user3386109

+2

あなたの 'divide'は' divide(int n、double x) 'という2つの引数をとりますが、あなたは' sum = sum + sign * divide(x) 'だけでそれを呼び出すことにも注意してください。これはあなたにエラーを与えるはずですが、 'double sum = 0.、divide();'として 'ローカル'分割を宣言しましたが、コンパイラはただ一緒に進むが、xを指定するだけなので、 nとする。その余分な 'n'を渡すとより意味をなさないはずです。 – LambdaBeta

+0

LambdaBetaが指摘した問題を回避するための一般的なヒント:関数プロトタイプを他の関数に入れず、関数プロトタイプを指定することは決してありません。標準的なプラクティスは2つあります。 1)すべての関数プロトタイプをファイルの先頭に置きます。関数定義をコピーし、ファイルの先頭に貼り付け、セミコロンを追加します。 2)関数を逆順に並べ替えます。つまり、 'divide'がファイルの先頭にあり、' myCos'、 'mySin'、' myExp'、 'main'がファイルの最後に続きます。このようにして、関数定義は関数プロトタイプとして機能し、プロトタイプのエラーを回避します。 – user3386109

答えて

1

あなたの問題は全身的なので、私はあなたに答えを落とすと考えました。

まず、関数を前方宣言に引き出します。これ以上:

double x, mySin(), myCos(), myExp(); 

代わりint main()の上にこれを置く:

double divide(int n, double x); 
double mySin(double x); 
double myCos(double x); 
double myExp(double x); 

また、これはあなたにこれらが何を文書化する絶好の機会を提供していません。これは実際にあなたの問題を解決するでしょう! (はい、ドキュメントがあるにもかかわらず、ちょうどコメント):

sum = sum + sign * divide(x); // this is sum += sign * x^?/?! 

ので、mySinを修正すると、次のようになります:

// Returns x^n/n! 
double divide(int n, double x); 

そのコメントを見てみると、突然mySinは意味がない(ノート

これは正しい出力を生成するはずですが、ループ出力文から論理を引き出すのは良い考えです。残念ながら、divide()にも問題があります。心の中でその文書を維持、それを見てみましょう:

double divide(int n, double x) 
{ 
int i; 
double div = 1.; 

for (i = 1; i < n; i++) 
    div = x/i; 

return div; 

} 

これは、等号がかなり右ではない、そのことだけ、修正することは非常に近いです。我々はx/iごとに反復したい。

for (i = 1; i < n; i++) 
    div *= x/i; 

ループは何回繰り返されますか。そのn-1回(0で開始した場合はn回になりますが、0で割り切れます)。のは、その問題を修正しましょう:

for (i = 1; i <= n; i++) 
    div *= x/i; 

は今、これは技術的には(「正常」の数字の近くのdivを保つことによって)最も正確な結果をもたらすであろう、乗算と同時に分裂を行っています。あなたが最初に分割する場合、あなたは本当に小さな数字を使用し始めます。そして、あなたが最初に乗算するなら、本当に大きな数字を使い始めるでしょう。いずれにしても、精度は失われます(2倍は中程度の数値で最も正確です)。

除算ループ:

for (i = 1; i <= n; i++) 
    div /= i; 

乗算ループ:ほとんどの入力の場合

for (i = 1; i <= n; i++) 
    div *= x; 

、それがすべてで大きな違いをすることはありません、あなたはループを離れて、それがに変わることを分割しない場合。しかし、あなたは '極端な'値を持っている場合、ダブルスを殺すことになります。たとえば、最初に乗算する場合、x = 1000を使用すると、実際に分割を開始する前に、doubleのスペースを使い果たすことになります。ダブルはちょうどそれを処理することはできませんので、結果は、ナノになります。同様に反復(30の代わりに30000000)を実行すると、明らかに時間がかかります(もちろん、約100000倍長くなります)。しかし、最初に割り算すると、倍になる前にダブルをゼロにすることになります。あなたは0の結果を得るでしょう(注:私はこれをテストしませんでした、これは理論です)。コンパイラが最適化の機会を見て、あなたのためにそれを取ることも完全に可能です。

関連する問題