プログラミング入門I
2023.11.13
if 文 その2
今回も残念ながらエラーの出るプログラムが出てきました.採点の対象外となりますので,提出の際には動作を確認の上アップロードしてください.
実行時エラー: b2303(if 文内での条件式に = を使用) b2353(関係ないゴミがソース中に混入) 以下は例によって問題のあるプログラムの例です.参考にしてください.
if (r ** 2) == x ** 2 + y ** 2:
print(f'Point P({x},{y}) is on the circumference of a circle with radius {r}.')
elif r ** 2 < x ** 2 + y ** 2:
print(f'Point P({x},{y}) is out of a circle with radius {r}.')
else:
print(f'Point P({x},{y}) is in a circle with radius {r}.')
上のものは中身は間違っていません.ただ,elif 節などが出てくるたびに空行が入っています.この場所には空行は入れないのが通常の書き方です.
if a > x > -a and a > y > -a: print(f'Point P({x}, {y}) is in a circle with radius {a}.') elif a < x or x < -a or y > a or y < -a or x == a and y !=0 or x == -a and y != 0 or y == a and x != 0 or y == -a and x !=0: print(f'Point P({x}, {y}) is out of a circle with radius {a}.') else: print(f'Point P({x}, {y}) is on the circumference of a circle with radius {a}.') |
今回結構見られた間違いです.円の内側かどうかは半径以外に判断するものはありません.単純に座標で場合分けすることは,たとえ整数値のみを扱うとしても相当細かく場合分けする必要があり,現実的ではありません.しかも,上の処理は間違った結果にもなります.
半径が4以上の円では点 (3, 3) のように円の外側になる座標が出てきます.
if -x < y < x and -x < z < x: print(f'Point P({y}, {z}) is in a circle with radius {x}.') if y <= -x or z <= -x or y >= x or z >= x: print(f'Point P({y}, {z}) is out of a circle with radius {x}.') if y == x and z == 0: print(f'Point P({y}, {z}) is on the circumference of a circle with radius {x}.') if z == x and z == 0: print(f'Point P({y}, {z}) is on the circumference of a circle with radius {x}.') if y == -x and z == 0: print(f'Point P({y}, {z}) is on the circumference of a circle with radius {x}.') if z == -x and z == 0: print(f'Point P({y}, {z}) is on the circumference of a circle with radius {x}.') |
今回のように円の内側か,外側か,それとも円周上か,のようにどれか一つに必ず収束するような条件分岐では,上のように if の羅列は適切とは言えません.授業中にも説明しました.(処理も先ほどと同様間違っていますし)
L = x^2 + y^2 R = r^2 |
べき乗の演算子は ^ ではありません.この演算子は教科書の p.126 (旧版ではp.124)にあるようにビット排他的論理和です.動作はIDLEのコンソールで,例えば,
>>> 2^3
などとやって試してみてください.
if distance_from_origin < num: print(f" Point({point_x}, {point_y}) is in a circle with radius {num} .") elif distance_from_origin == num: print(f" Point({point_x}, {point_y}) is out of a circle with radius {num} .") else: print(f" Point({point_x}, {point_y}) is on the circumference of a circle with radius {num} .") |
ちょっとした間違いなんですが,自分で実行して気づきませんでしたか.何度も実行してみて,処理に間違いがないか,よく確認してから提出しましょう.
if num1*num1==num2*num2+num3*num3: print('on the circumference of ',end='') elif num1*num1 |
最後が elif というのは良くないですね.今回は else ですね.
if num2**2==num1**2 and num3==0: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') elif num2==0 and num3**2==num1**2: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') elif num2**2+num3**2 < num1**2: print(f'Point P({num2}, {num3}) is in a circle with radius {num1}.') else : print(f'Point P({num2}, {num3}) is out of a circle with radius {num1}.') |
円周上の判定に無駄なものがありますね.
さて,以下にお示しするのは,かつて危惧を紹介していた場合分けの鬼への道へ落ち込んでしまいそうな予備軍の方々です.闇落ちしないよう,以後は注意してください.
if num1==num2 and num3==0: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') if -num1==num2 and num3==0: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') if num1==num3 and num2==0: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') if -num1==num3 and num2==0: print(f'Point P({num2}, {num3}) is on the circumference of a circle with radius {num1}.') if num1 |
これだけ if を並べると当然見過ごしも発生します.その結果,例えば以下のように2回表示する例も出てきます.
Point P(4, 5) is out of a circle with radius 2. Point P(4, 5) is a circle with radius 2. |
if x == num1 and abs(y) == 0: print(f'Point P({x},{y}) is on the circle of a circle with radius {num1}.') elif abs(x) == 0 and y == num1: print(f'Point P({x},{y}) is on the circle of a circle with radius {num1}.') elif abs(x) == 3 and abs(y) == 4 and num1 == 5: print(f'Point P({x},{y}) is on the circle of a circle with radius {num1}.') elif abs(x) == 3 and abs(y) == 3 and num1 == 4: print(f'Point P({x},{y}) is out of a circle with radius {num1}.') elif abs(x) == 4 and abs(y) == 4 and num1 == 5: print(f'Point P({x},{y}) is out of a circle with radius {num1}.') elif abs(x) < num1 and abs(y) < num1: print(f'Point P({x},{y}) is in a circle with radius {num1}.') else: print(f'Point P({x},{y}) is out of a circle with radius {num1}.') |
if r == 1 and x == 0 and y == 0: print(f'Point P({x}, {y}) is in a circle with radius {r}.') elif x == r and y == 0: print(f'Point P({x}, {y}) is on the circumference of a circle with radius {r}.') elif x == 0 and y == r: print(f'Point P({x}, {y}) is on the circumference of a circle with radius {r}.') elif x == -r and y == 0: print(f'Point P({x}, {y}) is on the circumference of a circle with radius {r}.') elif x == 0 and y == -r: print(f'Point P({x}, {y}) is on the circumference of a circle with radius {r}.') elif r == 1 and x == 0 and y in {-5, -4, -3, -2, 2, 3, 4, 5}: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 1 and x in {-5, -4, -3, -2, 2, 3, 4, 5} and y == 0: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r < x: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r < y: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif x < -r: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif y < -r: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif -r < x < r and -r < y < r: print(f'Point P({x}, {y}) is in a circle with radius {r}.') elif r == 2 and x == 0 and y in {-5, -4, -3, 3, 4, 5}: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 2 and x in {-5, -4, -3, 3, 4, 5} and y == 0: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 3 and x == 0 and y in {-5, -4, 4, 5}: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 3 and x in {-5, -4, 4, 5} and y == 0: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 4 and x == 0 and y in {-5, 5}: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') elif r == 4 and x in {-5, 5} and y == 0: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') else: print(f'Point P({x}, {y}) is out of a circle with radius {r}.') |
最後のものは最悪です.全く評価できません.理由としては,今回の設問で,半径が 1 から 100 に,座標の範囲が -100 から 100 に変更された場合に全く対応できないことがあります.解答例のような処理であれば,発生させる乱数の範囲を変更するだけで対応できます.
この授業では,イメージをつかみやすくすることや,画面に表示させる際に狭い範囲で十分描画できることを想定し,大きな値を使用しないことが多々あります.だからと言って,その小さな変数の値に依存するような書き方をしてはプログラミングを学習する意味がありません.注意してください.
if 文について,基本的なことを学習しました.前回も紹介したツボの部分を再掲します.今回も引き続き if 文ですので,しっかりと理解していきましょう.
if 文のポイント
単純な if 文 | 条件式が真の場合に処理を行う |
if - else 文 | 条件式が真の場合にある処理を行い,偽の場合に別の処理を行う |
if - elif 文 | 条件式が真の場合にある処理を行い,偽の場合にはさらに別の条件式が真であれば別の処理を行う |
if 文の中にさらに if 文を入れることが可能です.そのような状態を 入れ子と言います.
if 文の条件式に従って実際に動作させる処理の文が複数になっても構いません.そのように複数の文が入る場合にそれらをスイート(組,ホテルのスイートルームのスイート)と言います.
if 文などのようにその効力が及ぶ範囲を明確に示す必要があるのが制御構造というもので,今後登場する for 文など重要な項目があります.その際に,スイートの範囲がどこまでかを示すのに,Python ではインデント(字下げ)を使用します.他の言語ではカッコを使用したり,ブロックの終了を示す文字列を入れたりしますが,Python では区切りの記号を使用しませんので,このインデントが非常に重要です.インデントが正しくないと実行時にエラーが出ますので,注意してください.
インデントの例
if hoge: Do this Do that |
上のようにスイートのインデントがそろっていない場合には,下図のようなエラーとなります.
一方で,以下のソースのような場合,各文のインデントがバラバラでもエラーとはなりません.ただし,見づらいので,決してこのような書き方を推奨はしません!
if hoge: Do this elif hege: Do that else: Do it |
教科書 p.70 List 3-31 で説明のある値の交換はとても便利な機能なので,この授業でも頻繁に使用することになると思います.活用してください.
教科書 p.72 の sorted 関数も便利な関数です.本来は複数の値を [ ] で囲むリストが登場したところ(教科書 p.164, 旧版では p.162)で詳しく扱うものですが,今回ここで紹介されていますので,適宜使用してください.
リストとは複数の値(数値や文字列等)を一つの名前で管理できる便利なもので,通常は配列と呼ばれるものです.配列を使用できるようになると,実用的なプログラムを作成することが可能になりますが,残念ながらプログラミング入門IIの範囲です.
また,教科書 p.73 の代入演算子と代入式は旧版には無いので,今回は省略します.
旧版の教科書では出てこない match 文ですが,他の言語では switch 文として用意されている機能とほぼ同じです.今回の授業では扱わないこととしますが,一応見ておいてください.
重要なことが網羅的にまとめてありますので,しっかりと読んでおいてください.
今回の演習問題です.
宿題が公開されるのは明日火曜日10:00の予定で,締切りは来週の月曜日11月20日の10:00です.レポート提出システムを使用します.
次回は教科書のp.90-101(旧版は p.88-99)の範囲を学習しますので,予習をしてきてください.
また,次回はいよいよ第1回目の確認テストを行います.範囲は教科書の p.73 までです.復習をしっかりしておきましょう.