- ベストアンサー
Pythonプログラムが狙い通りに動かない
- 学習目的で組んだPythonプログラムが予想とは異なる結果を出力し、メモリーエラーが発生しています。
- プログラムは入力フォームを表示し、指定範囲の数の中に含まれる素数の数を確率的に予測するものです。
- しかし、試行錯誤を重ねても想定外の結果が出力されたり、メモリ不足のエラーが発生しています。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
回答No.3、4で間違った指摘をしてしまったので、プログラムを書き直してみました。全角空白を使って字下げをしているので、適宜置き換えてから実行してください。 def sosuu_kuzi(trials): total = 0 for cnt in range(trials): from random import randint a_num = randint(2,search_range) for num in range(2,a_num): if a_num % num == 0: break else: total += 1 print((total * 100 / trials), "%") sosuu_kuzi(10000) このプログラムでsearch_rangeの値を1000とすると、17.35 %のような出力が得られました。乱数のために毎回結果は変わります。 sosuu_kuziの引数は試行回数です。 while True:による無限ループは消しています。 a_numが素数だったときにリストにappendする必要を感じなかったので、単純にtotalでカウントするようにしました。
その他の回答 (5)
- _kappe_
- ベストアンサー率68% (1581/2304)
回答No.3、4の者です。 私が字下げを勘違いしていたようです。質問文で意図していたのは for num in range(2,a_num): if a_num % num == 0: break else: list_num.append(1%1000) ではなくて for num in range(2,a_num): if a_num % num == 0: break else: list_num.append(1%1000) (else:はifではなくてforに対応する) だったんですね。 これがあるからこのサイトでPythonは扱いづらい。
お礼
ありがとうございます。 質問するときは、インデント部にアンダーバーを入れた方が良さそうですね。
- _kappe_
- ベストアンサー率68% (1581/2304)
回答No.3について一つ訂正です。 ・num=5のとき、a_num%5=0なので... と書きましたが、a_numが5のときnumの値は4で終わりで、5になることはありませんでした。失礼しました。
お礼
お礼が遅れた申し訳ありません。 回答ありがとうございました。
- _kappe_
- ベストアンサー率68% (1581/2304)
>いくら調べても試行錯誤しても間違った結果が >出力される原因が見つからなかったんです。 おかしな点は多々ありそうですが、ひとまずこの部分だけ。 for num in range(2,a_num): if a_num % num == 0: break else: list_num.append(1%1000) a_numが素数のときにlist_numに追加したいのかなと想像しますが、具体的な数字で順番に考えてみてましょう。 たとえばa_numが5だとすると ・num=2のとき、a_num%2=1なのでlist_numに追加 ・num=3のとき、a_num%3=2なのでlist_numに追加 ・num=4のとき、a_num%4=1なのでlist_numに追加 ・num=5のとき、a_num%5=0なのでbreakでfor num in range(2,a_num)のループを抜ける となって、list_numに3回も追加されてしまいました。a_numが17なら15回追加されます。 一方で、a_numが2のときにはlist_numに1回も追加しないままループを抜けてしまいます。 この動きは意図通りですか?
お礼
お礼が遅れた申し訳ありません。 回答ありがとうございました。
補足
回答ありがとうございます!早速修正してみます。 そういえば、このプログラムは「みんなのPython」 という参考書の第4版のサンプルコード(144ページ) を元に書いたんですが、そこの説明文には 「このプログラムにある else 以下のブロックは、 break 文が実行されずにループを抜けたとき にのみ実行されます。」と書いてありました。 (以下にサンプルコードの内容を示しました。) a_num = 59 for num in range(2, a_num): if a_num % num == 0: print(a_num,”は素数ではありません”) break else: print(a_num,”は素数です”) では、以下のサンプルコードで、a_num = 25 と書き換えて実行した場合、 "25は素数です" (2で割った余りが1なので) "25は素数です" (3で割った余りが1なので) "25は素数です" (4で割った余りが1なので) "25は素数ではありません" (5で割った余りが0なので、 ここで初めて break 文が実行) という結果にならないのはなぜですか?
- asciiz
- ベストアンサー率70% (6803/9674)
いろいろ問題があります。 while True で開始しているなら、どこかに break でもないとループを抜けられませんが、このプログラムに一つだけある break は for を抜けるのみなので、whileループは永遠に終了しません。 > list_num.append(1%1000) %演算子は、剰余です。なので 1%1000 は常に1です。 なので、あなたの >そうでなければ(1/1000 ) を加える この考えとは食い違っています。 そして再度こちら、 > list_num.append(1%1000) 永遠に脱出しないループ内で、list_num リストを増やし続けているので、最後にはメモリを食い尽くします。 それが「メモリ不足」というエラーとなって表示されました。 ---- まあ本質的には、while True でなく、いつかは必ず終了する条件でループするのが良いと思います。
お礼
親切な回答をありがとうございます。 勉強になりました。
補足
皆さんのおかげで、ループ文に関する理解は深まったんですが、 僕が本当に困っていたのは絶対におかしい結果が出力される事だったんです。 (質問文にしっかり書いておくべきでしたね…) 質問分が分かりにくくて申し訳ないんですが、 絶対ありえない結果が表示されるというのは、例えば 1~100までの数の中から素数を探したのに、45.112 といった風に出力される事を言っていました。 1~100 までの数の中には25個の素数があるので、25.355 といった結果が返ってこないと狙い通りに動いたとは言えないのです。 なお、何もエラーが出ないプログラム自体は前回僕が質問した時に 回答者様のおかげで作れたんですが、あの時から いくら調べても試行錯誤しても間違った結果が 出力される原因が見つからなかったんです。 前回の質問のページのURL:https://okwave.jp/qa/q9745091.html
- okwavey4
- ベストアンサー率18% (99/546)
ろくに見てはいないけど、無限ループの処理があるから、どんなケースでも必ずループを抜けるのか確認すべきだと思いました。 >絶対おかしいと思うんですが… そんなことないですよ。 質問内容が技術者とは思えませんが、カテゴリー名見落としてますし、エラーメッセージの方が信頼できます。
お礼
回答ありがとうございます。 質問のカテゴリは 学問→応用科学→情報工学 にすればいいですか?
お礼
親切な回答をありがとうございます。 早速修正してみます!