• ベストアンサー

C言語のwhile文を使った素数判定プログラムで…

次に示すプログラムは、100までの素数を表示するものです。 見てのとおり、C言語のwhile文を使って書いてあります。 #include <stdio.h> int main(void) { int a, b; int flag = 0; a = 2; b = 2; while(b <= 100){ *ここ* while(a < b){ if(b%a == 0){ flag = 0; break; } else{ flag = 1; } a++; } if(flag == 1){ printf("%dは素数\n", b); } b++; } getch(); return 0; } 最初、手本を参考にしながら上記のように書きましたが、うまく機能せず、3から100までの数字すべてが素数であると表示されました。 どこが間違っているのかと、手本と厳密に見比べてみたら、8行目の a = 2 が*ここ*と書いてある場所に書かれていました。 まさかないだろうと思いつつ、もとあったのを消して*ここ*に書き換えたら、正しく素数が表示されるようになりました。 値を代入する場所が違うだけで、なぜこのような違いが起こるのか全く理解できません。 教えてください。 (一応、書いておきますが使っているコンパイラはBorlandのやつです コンパイラのせいってことはないですよね)

質問者が選んだベストアンサー

  • ベストアンサー
回答No.4

>つまり、a = 2 はwhileの{}に入れないといけないということで、あってますか? はい。 #2は無視か,flag = 1の誤り(変数の初期化時も)。勘違いしていた,すまん。 >下のほうは、なぜ値が増えていかないのですか? 毎回 a=0; が実行されるから。 #1の「階乗」とは言わないだろうな。なんと言うか思いつかんけど。

noname#183708
質問者

お礼

> >下のほうは、なぜ値が増えていかないのですか? > 毎回 > a=0; > が実行されるから。 この文でかなりすっきりしました。 a = 0 は一度実行されたら、それ以降は関係ないと思い込んでいました。 たしかに、printf("debug:%d",a); で見た時もaの値は毎回2にリセットされてました。 1から10まで全部表示されるのを階乗とは言わないですね… すみません、訂正します… flagはどこに入れても問題ありませんが、なんか、こうするといいっていうのがあるみたいですね。(自分には分かりませんが) ひとまず、解決まで導いていただきありがとうございました。

その他の回答 (5)

回答No.6

>#5 >flag の初期化」は意味をなしません うん,自分でも解ってて, >flag = 1; >a = 2; >while (a < b) { >if (b % a == 0) { >flag = 0; >break; >} >a++; >} 自分はこの形を望んでいたからflagを初期化する処理を書いたんだけど, コードを書いて説明するのが面倒くさかったものだから >2は無視か, っていう部分が入っているの(汗。やっぱり無駄に混乱させる分俺の回答自体が害悪になっちゃったかなあ?

noname#183708
質問者

お礼

結論から言うと、Tacosanさんと同じように flag = 1 にする else はいらない、 だから、flag を 1 で初期化すべしってことですね。 害悪なんてことはないです。 #4は自分が求めていたような回答でした。 何回も質問を見ていただき、ありがとうございました。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

えぇと, このプログラムにおいて「flag の初期化」は意味をなしません>#4. だからどこにあってもいいしどんな値にしてもいいのですが, 本質をいうとこのプログラムは「動作はあっているけど論理的に間違っている」と思います. 内側の while ループで if の else 部分が無駄ですし, 変数 flag が「b が素数なら 1, そうでなければ 0」という値を取る以上「素数かどうかをチェックする途中で 1 にする」のは誤解を招きかねません. flag = 1; a = 2; while (a < b) { if (b % a == 0) { flag = 0; break; } a++; } の方が「しなければならないことを過不足なく表している」という点でより正しい. もっとコンパクトにするなら a = 2; while (b % a != 0) { a++; } でも (あとの if の条件を a == b に変えれば) 同じような動作になりますが, あんまりお勧めしない.

noname#183708
質問者

お礼

回答ありがとうございます。 flag = 0 としていた(flag の初期化)のは、もとのプログラムでは何も意味をなしていなかったんですね。 最初に flag = 1 とすることで else{ flag = 1; } の部分が省けて、分かりやすくすることができました。 それ以上コンパクトにすると自分には少し分かりづらそうな気がするのでやめておきます。 論理は分かりますが…

  • notnot
  • ベストアンサー率47% (4900/10358)
回答No.3

プログラムは、書いてある命令を書いてあるとおりに実行していきます。書いてある内容が変われば実行結果は変わるのが当然です。もちろん、たまたま変わらない場合もありますが、この場合は変わると言うことです。 a=0; for(i=0;i<10;i++){ a++; printf("%d\n",a); } と、 for(i=0;i<10;i++){ a=0; a++; printf("%d\n",a); } の違いがわかりますか?

noname#183708
質問者

お礼

himajin100000さんに違いを教えていただいて解決しました。 a++が実行オブジェクトであるのと同じようにa=0も実行オブジェクト ただ、それだけのことが分からずに悩んでたみたいです。 ありがとうございました。

noname#183708
質問者

補足

回答ありがとうございます。 違いはよく分かりません。 でも、やってみたら、上は1の階乗が表示されましたが、 下は1だけが表示されました。 下のほうは、なぜ値が増えていかないのですか?

回答No.2

あともうひとつ。flag = 0もそこにあるべきだと思う。

回答No.1

やっていることがそもそも違うから その処理だと 2は素数(a == 2,b==2) 3は素数(3 % 2 == 1) 4は素数(4 % 3 == 1) ←ここで 4 % 2 == 0をチェックしない 5は素数(5 % 4 == 1) ←ここで 5 % 3 == 0, 5 %2 == 0はチェックしない 6は素数(6 % 5 == 1) ←ここで 6 % 4 == 0, 6 % 3 == 0, 6 % 2 == 0はチェックしない となっちゃうよね? while(a < b){ printf("debug:%d",a); /* ここで値を見張ってみればたぶん一目瞭然 */ /* 略 */ }

noname#183708
質問者

補足

回答ありがとうございます。 やっていることが違うのは分かりました。 つまり、a = 2 はwhileの{}に入れないといけないということで、あってますか?

関連するQ&A