🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

1回答

1377閲覧

フィボナッチ数列において無限ループが発生してしまう

katkey

総合スコア15

C

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

0グッド

0クリップ

投稿2020/11/28 00:25

条件

f(0)=3,
f(1)=0,
f(2)=2,
f(n)=f(n-2)+f(n-3)
で表されるフィボナッチ数列をn=1から繰り返したときに、
f(n)がnで割り切れるnを小さい方からkとし、その値をh(k)としたときに、h(32)の値を知りたいです。

該当のソースコード

#include<stdio.h> #define N 10000 int fibo(int n){ if(n==0) return 3; if(n==1) return 0; if(n==2) return 2; if(n>=3){ return fibo(n-2)+fibo(n-3); } } int main(void){ int k,num,cnt=0; while(cnt<=32){ for(num=1;num<N;num++){ k=fibo(num); if(k%num==0){ cnt++; } } } printf("%d",k); return 0; }

###発生している問題
ループが発生して正しい答えが得られません。分かる方いたら解答をお願いします。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2020/11/28 00:33

ループが発生しているのはどこですか?
katkey

2020/11/28 00:37

デバックの使い方が分からないので、ループの発生個所が分かりません。申し訳ないです。
episteme

2020/11/28 00:40

mainのfor-loop内でcntをプリントしてみよう。cntが32に達しないためにwhile-loopを抜けられないのでは?
katkey

2020/11/28 00:47

cntの値が22で止まってしまいます。
episteme

2020/11/28 01:45

だからでしょ。そもそもcntの意味は?
guest

回答1

0

ベストアンサー

  • f(n)の値がf(77)から32ビット符号付き整数の範囲を超えてしまうため、intが32ビット符号付き整数の処理系では正常に計算が行なわれない。long long intに変更すれば、今回の答えは得られる。
  • main()での処理がおかしい。forループでnumの値を1からN-1まで増やしながら、条件にあうnumの値が見つかったらcntを1増やせばいい。
  • fibo()を呼び出すたびにフィボナッチ数列を再帰計算しているが、それまでの計算結果をキャッシュしておけば、処理にかかる時間がてきめんに減る。

C

1#include <stdio.h> 2#define N 10000 3 4long long int answer_cache[N]; 5 6long long int fibo(int n) 7{ 8 if (n == 0) return 3; 9 if (n == 1) return 0; 10 if (n == 2) return 2; 11 if (n >= 2) { 12 if (answer_cache[n] == 0) { 13 answer_cache[n] = fibo(n - 2) + fibo(n - 3); 14 } 15 return answer_cache[n]; 16 } 17} 18 19int main(void) 20{ 21 int cnt = 0; 22 for (int num = 1; num < N; num++) { 23 long long int k = fibo(num); 24 if (k % num == 0) { 25 cnt++; 26 printf("fibo(%d) = %lld (cnt %d)\n", num, k, cnt); /* 途中経過 */ 27 } 28 if (cnt == 32) { 29 printf("%lld", k); 30 break; 31 } 32 } 33 return 0; 34}

投稿2020/11/28 00:42

Daregada

総合スコア11990

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

katkey

2020/11/28 01:05

while文を使うのではなく、breakでループを抜けた方がよいということでしょうか? また、キャッシュというのは配列に数字を保存するということでよいでしょうか?
Daregada

2020/11/28 01:13

元々のコードでは、mainの中でforループをwhileループで囲んで2重の繰り返しをしていますが、意味がありません。1回のforループですべての答えが見つかります。 キャッシュは、「値をどこかに保存しておいて後でまた使う」ぐらいの意味合いで、今回は記述を簡単にするためにグローバルな配列を利用していますが、値を保存しておけるならどのような方法でも構いません。
katkey

2020/11/28 01:40

解答ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問