質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • C

    3687questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

課題の考え方がわかりません

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 286

tocchi

score 2

前に質問してからしばらく考えてみた結果今だによくわからないままなので再質問します。
関数y=sin(x)のテイラー展開は次式で求められる。n番目の値が1*10^-8よりも小さくなるまでの級数を求め、任意のxに対するsin(x)を近似して求めよ。
y=sinx=Σ((-1)^n /(2n+1)!)*x^2n+1
というものをc言語を使って求めるという課題が出ました。コードを書いてみたのですが答えが0.000000000となってしまい正しい答えが出ません。直した方がいいところを教えていただきたいです。できるだけわかりやすく教えていただきたいです。

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

int main(void){
float n,x,sum,coeff_mole,coeff_deno,vari,series;
printf("任意のxを入力>>");
scanf("%d",&x);
n = 0.0;
sum = 0.0;

while(1){
//mole_計算
coeff_mole = pow(-1.0,n);

//deno_計算
coeff_deno = 1;
for(int i = 2*n+1;i>0;i--){
coeff_deno = coeff_deno+i;
}

//vari_計算
vari = pow(x,2*n+1);

//series_計算
series = coeff_mole/coeff_deno*vari;

if(series >= pow(10,-8)){
sum = sum + series;
}else{
break;
}
n++;
}
printf("近似値は>>%.10f",sum);
return 0;
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

checkベストアンサー

+3

考え方は問題ありませんが、コーディングで3点ほどミスがあるようです。

1. scanf の変換指定が正しくありません。
floatを入力させるための変換指定子は%fです。
 
2. 階乗の計算が加算になっています。
「//deno_計算」の部分を再確認してみてください。
 
3. 終了条件の判定に誤りがあります。
nが奇数のときの項は負の数になるので、その時点で必ず終了してしまいます。

3に関しては、例えば下記のような修正はいかがでしょうか。

//series_計算
series =  coeff_mole / coeff_deno * vari;

if (fabs(series) >= pow(10, -8)) {
    sum = sum + series;
}

以上の3点を修正すれば、とりあえず目的通りに動くはずです。

こういうデバッグでは、自分が思った通りの処理ができているかをしっかり確認すると良いですよ。
(途中結果を出力してみる、IDEのデバッグモードを使うなど。)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/01 19:10

    > 3. 終了条件の判定に誤りがあります。について
    x > 0の時、第2項目が負になり、初項しか足されない
    x < 0の時、第(2k + 1)項目が負になるので結果が0になる
    これを解決する方法の一つはマクローリン展開のそれぞれの係数の「絶対値」をとればいいと思います。
    実際にコードにすると while(fabs(series) >= pow(10,-8)){}

    キャンセル

  • 2018/07/01 20:55 編集

    ご指摘ありがとうございます。
    恥ずかしながら、x < 0 の場合がごっそり頭から抜けておりました。
    コードは修正しておきました。

    キャンセル

  • 2018/07/01 23:21

    @shiron46さんへ
    ソースコードを修正してくださり、ありがとうございます。

    キャンセル

+1

今までの回答以外に

  • if(series >= pow(10,-8)){
  • if(fabs(series) >= pow(10,-8)){

にすれば動くでしょう。seriesはcoeff_moleにより正と負をとりえますから絶対値にして比較しなければなりません。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

これだけでは正しく動かないのでさらに修正が必要なようですが、floatを入力させるためのscanfの書式は%fです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

とりあえず2点
scanfの使い方が違います。
テイラー展開の近似は任意の点では有効ではありません。基準点(この場合原点)近傍以外では無効です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/07/01 19:03

    >テイラー展開の近似は任意の点では有効ではありません。
    今回のsin(x)のマクローリン展開は |x| < ∞ で成り立つので任意の点で有効なはずですが....

    キャンセル

  • 2018/07/01 20:52

    マクローリン展開は原点を離れるほど誤差範囲が広がります。定義だけならできますけど。

    マクローリン展開による近似式はあくまでも有限多項式ですから、原点を離れるほど、最高次の項が優位となります。つまり、両端では単調増加または単調減少関数になるので、三角関数とは似つかない形になります。

    キャンセル

  • 2018/07/01 23:29 編集

    マクローリン展開について何か勘違いをしていませんか?
    たとえば、log(1 + x)だったら、収束半径は |x| < 1より xが1より大きい場合は誤差範囲は広がります。
    収束半径が∞でない場合はあなたのおっしゃる通りです。
    しかし、今回の関数はsin(x)です。sin(x)は収束半径が |x| < ∞ より、xがどの値であっても必ず
    右辺は収束し、左辺と等しくなります。(xがどんな値をとっても右辺はライプニッツの交代級数です。)
    詳しくは https://mathtrain.jp/sincostenkai をご覧ください。

    また、sin(x)のマクローリン展開は符号が交互に入れ替わるので単調増加関数でも単調減少関数でもありません。少しずつ値が増えたり、減ったりして、増える値、減る値の絶対値が小さくなり収束していきます。

    キャンセル

  • 2018/07/02 02:45

    どうやら、互いに話が噛み合っていませんね。私はコンピュータ近似の都合上の有限性を原因とした誤差について述べています。

    仰るとおり、無限に次数を高めれば収束範囲内で展開結果の誤差はゼロに近づきます。ただし、コンピュータ処理において無限はありえません。

    有限近似である限り、展開結果は有限多項式でしかなく、原点から充分離れた範囲では単調関数になります。

    キャンセル

  • 2018/07/02 14:00 編集

    なるほど、コンピューター近似の都合上の話ですか、誤解してすみません。
    ただ、回答の「テイラー展開の近似は任意の点では有効ではありません。」だと、今回のように
    語弊がある場合があるので「マクローリン展開を用いて、コンピューターでsin(x)の近似を求める際、あまり大きな値を入力だと誤差が出る」などのように書き直した方がいいでしょう。
    一般にマクローリン展開において収束半径が無限大の場合、任意の点で有効ですから.
    (n番目の値の絶対値が10^-8未満になるまで求めるのである程度までは誤差範囲は小さくて済みます。)
    ちなみに解決方法としては入力した値をn回転して、-pi <= x <= pi にすればいいでしょう。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • C

    3687questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。