前提
pythonにおけるrange関数についての質問です。
疑問点
まずは以下のコードをご覧ください。
python
1for i in range(2, 101): 2 for j in range(2, i): 3 if i % j == 0: 4 break 5 else: 6 print(i)
このプログラムは100以下のいわゆる素数を列挙する単純なプログラムで、実際この通りに実行しても問題なく動き期待通りの結果を吐き出すことが確認できます。しかし改めてデバッグモードで1行ずつ送っていくと、iが2の時に限りよくわからない挙動をしているように見えます。
i = 2 のとき2行目にあるrange関数はrange(2,2)という形になるわけですが、このときjに代入される具体的な数は明らかに存在せず、本来であれば i % j という計算を実行することすら不可能なはずです。しかし実際にはこのコードはエラーを吐くこともなく突然elseへと飛び、print(i)で2をアウトプットしてそそくさと i = 3 の場合の計算へと入っていきます。
なぜこのようなことが起きるのでしょうか?range(2,2)においてjに何が代入され、i % j の計算結果はどうなって、どういう条件式のもとで2が吐き出されるのでしょうか?そもそもrange関数はどういったコードで成り立っているのでしょうか?
ごく初歩的な質問で申し訳ありませんが、ご教示いただければ幸いです。
蛇足
pythonにかぎらずもう少し拡張した話になります。こちらについても見解をいただければ嬉しいですが、あくまで蛇足ですのでプログラミングに直接関係ないとご判断されるようでしたら無視していただいて構いません。
上記のコードはよく初心者向けのサイトなどによく使われており、説明部分には「2から順番に割り算を繰り返し、元の数より1小さい数になっても割り切れなかったら素数と判定する」みたいなことが書かれていることが多いです。
しかしこれもよくよく考えるとちょっと変で、最小の素数である"2"に限ってはまず一番最初に割り切れるかを試す"2"で割り切れてしまうため、素直に文面通りにアルゴリズムを組むと合成数と判定されてしまいます。また「元の数より1小さい数」は"1"であり、原文をそのまま解釈すると「2から1まで順番に数を大きくしていって割り切れるか試す」という全く意味の通らないアルゴリズムになってしまいます。
本来素数と判定するためには「1からその数まで順番に割っていき、1とその数自身でのみ割り切れたとき素数と判定する」というアルゴリズムが必要なはずで、多くのコードではこれを「1より大きくその数より小さい自然数では割り切れないとき素数と判定する」というアルゴリズムで実装しているのだと思いますが、こと"2"に限っては「1より大きく2より小さい自然数」が存在し得ないためこのような問題が発生してしまうのだと思われます。実際に実用的かはともかくとして、このなんとなく気持ち悪い部分をスマートに解消するようなアルゴリズム・コードを上手いこと組めないものでしょうか?
回答7件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。