電話 0422-27-7828チャットで質問無料相談を予約

武蔵野個別指導塾の特徴

【情報I】プログラミングの基礎②を図解で総まとめ—条件分岐・繰り返し・条件式と論理演算|武蔵野個別指導塾

【情報I】プログラミングの基礎②を図解で総まとめ—条件分岐・繰り返し・条件式と論理演算のアイキャッチ 武蔵野個別指導塾
X LINE Facebook

条件分岐の選び方と繰り返しの終了を、Pythonの例題と3枚の図でたどります。トレース表を使い、境界の値や更新の順序を自分で確かめられるように練習しましょう。

よくあるのは、定期テスト前の自習室の白板の前で、繰り返しのプログラムを指しながら「3回足すことはわかるのに、どうして答えが6になるのか説明できない」と手が止まる場面です。命令を上から読むところまではできても、途中で前の行へ戻ると、変数の値をいつ書き換えたのか見失いやすくなります。条件分岐でも、条件を満たした行を全部実行するのか、最初の1つだけ実行するのかが混ざりがちです。

この単元の中心は、実行する道筋と、その時点の値を分けて追うことです。条件式は進む道を決め、代入は次の処理で使う値を変えます。その2つを紙の上に残せば、短いプログラムを頭の中だけで動かす必要はありません。分岐の境界、繰り返しの回数、最後に表示される値まで、根拠を添えて説明できるようにしていきましょう。

この単元で身につけること

前に学んだ変数と代入、順次・分岐・反復の考え方が、この単元の土台になります。足し算自体ができても、代入の右辺をどの時点の値で計算するかが曖昧だと、反復の途中で結果がずれます。まず1行を確実に実行し、その1行を条件や繰り返しの中に置いたときの動きを読む、という順序で学びます。

基本の考え方

比較の結果を条件にする

条件式とは、処理を選ぶために判定する式です。ここでは整数を比較し、結果をTrue(真)またはFalse(偽)で考えます。たとえば、点数を表すscoreが60なら、score >= 60は真、score > 60は偽です。「以上」は境界を含み、「より大きい」は境界を含みません。日常の言い方を式に移すときは、境界ちょうどの値を実際に入れると取り違えに気づけます。

比較演算子 意味 scoreが60のときの例と結果
== 等しい score == 60は真
!= 等しくない score != 60は偽
< より小さい score < 60は偽
<= 以下 score <= 60は真
> より大きい score > 60は偽
>= 以上 score >= 60は真

Pythonの=は代入、==は等しいかどうかの比較です。score = 60はscoreに60を代入する命令であり、値を尋ねる条件式ではありません。また、total = total + nは数学の等式として解くものではなく、今のtotalにnを加えた値を、同じtotalへ入れ直す命令です。右辺を先に計算し、その結果で左辺を更新する順序を守ります。

複数の条件をつなぐ論理演算も使います。andは両方が真のときだけ真、orは少なくとも一方が真なら真、notは真と偽を反転させます。orの「または」は、両方が真の場合も含みます。「どちらか片方だけ」と読み替えないことが大事です。次の表では、AとBを真偽の値として扱っています。

A B A and B A or B not A
真 真 真 真 偽
真 偽 偽 真 偽
偽 真 偽 真 真
偽 偽 偽 偽 真

「10以上20以下」は10 <= x and x <= 20です。「10未満または20より大きい」はx < 10 or x > 20となります。前者の範囲に入らないことはnot (10 <= x and x <= 20)とも書けます。括弧を付けると、否定している範囲がはっきりします。Pythonでは比較が論理演算より先に評価され、論理演算同士ではnot、and、orの順です。ただし、読み手が迷いそうなら括弧でまとまりを示すとよいでしょう。

Pythonには数や文字列を条件として評価する使い方もありますが、まずは比較の結果を組み合わせる形で理解します。また、andは左が偽なら右を評価せず、orは左が真なら右を評価しません。これを短絡評価といいます。真理値表は最終結果を整理したもので、常に両側の式が実行されるという意味ではありません。

ifは道を選び、字下げは処理のまとまりを示す

ifは条件が真のときに、その下の処理を実行します。elseを付けると、偽のときに実行する処理も書けます。図1のように、ひし形で条件を判断し、真と偽のどちらか一方の道を通った後、共通の処理へ合流します。矢印をたどると、両方の箱を通るわけではないことが見えます。

図1 条件の真偽で処理を選び共通の道へ戻る流れ

図1の「条件」は真偽を決める場所、「処理A」「処理B」は選ばれた後に実行する場所です。条件を調べただけで変数が自動的に変わるわけではありません。値が変わるのは、選んだ道の中で代入などを実行したときです。

Pythonでは、ifなどの行の末尾にコロンを書き、その中の処理を字下げします。この字下げをインデントと呼びます。例では半角空白4個を1段としてそろえます。字下げは見やすさだけの飾りではなく、どこまでが同じ処理のまとまりかを示します。同じ深さまで戻った行は、そのまとまりの外です。

条件を3段階以上に分けたいときはelifを使います。ifから順に調べ、最初に真になった箇所の処理だけを実行し、残りのelifやelseを飛ばします。どれも真にならなかった場合はelseへ進みます。elseは省略でき、省略した場合は該当する処理をせずに分岐の後へ進みます。elifは「前までの条件がすべて偽だった場合に、次を調べる」と読めば、並び順の意味がつかめます。

forとwhileを値の動きで区別する

forは、指定した範囲などから値を順番に取り出して反復します。整数の列を扱うrangeは、range(開始, 終了)なら開始を含み、終了を含みません。range(1, 4)から取り出す値は1、2、3です。range(4)のように開始を省略すると0から始まり、0、1、2、3となります。3つ目の引数で増分を指定でき、range(2, 8, 2)なら2、4、6を取り出します。

whileは、条件が真である間、同じまとまりを繰り返します。条件を調べてから処理に入るので、最初から偽なら本体は1回も実行されません。処理を終えたら条件へ戻り、その時点の値で判定し直します。「1度真になったので、ずっと真のまま」と考えないことが大切です。

回数や走査する範囲があらかじめ定まる場合はforが書きやすく、到達した値や状態に応じて止める場合はwhileが書きやすい傾向があります。ただし、forが常に固定回数、whileが常に回数不明と決まっているわけではありません。この後のwhileも、値の変化を計算すれば実行回数を求められます。ここでは途中で反復を抜ける命令は使わず、通常の終了までを追います。

例題で解き方を確かめる

例題1 2つの条件を両方満たすか

点数scoreが60以上で、提出済みを表すsubmittedが真のときに「確認完了」と表示します。それ以外は「要確認」と表示します。次のプログラムの出力を求めましょう。入力値を増やさず、まず境界に当たる60を確実に判断します。

score = 60
submitted = True
if score >= 60 and submitted:
    print("確認完了")
else:
    print("要確認")
  1. scoreとsubmittedの初期値をそれぞれ60、Trueと書きます。条件を読む前に値を固定すると、文字の意味と判定結果を混同しません。
  2. score >= 60を調べます。60は60以上なので真です。等号が含まれるため、境界ちょうどでも条件を満たします。
  3. submittedも真なので、andでつないだ全体は真です。両方の条件を満たす必要があるため、一方だけを見て決めてはいけません。
  4. ifの中の表示を実行し、elseの表示を飛ばします。分岐は1本を選ぶので、2つの文字列を続けて表示することはありません。

出力は次のとおりです。

確認完了

点数が十分でも未提出なら、andの右側が偽となり「要確認」です。条件をorへ変えると、点数か提出状況のどちらか一方で通る別の判定になります。演算子1語の違いが、何を必要条件とするかの違いにつながります。

答え:確認完了

例題2 elifの並び順を読む

scoreが80以上なら「A」、そうでなく60以上なら「B」、それ以外なら「C」と表示します。scoreが85のとき、どの文字が表示されるでしょうか。85は80以上でも60以上でもあることに注目してください。

score = 85
if score >= 80:
    print("A")
elif score >= 60:
    print("B")
else:
    print("C")
  1. 最初のscore >= 80を判定します。85は80以上なので真です。上から順に調べる規則があるため、下の条件から先に選びません。
  2. ifの中で「A」を表示します。最初に真になった枝を選ぶので、この時点で選択が決まります。
  3. elifとelseを飛ばして分岐の後へ進みます。score >= 60も数学的には真ですが、この実行ではその条件を調べるところへ進みません。

出力は次のとおりです。

A

もし60以上を先に書けば、85は最初の条件に当たり、「B」とする枝に入ってしまいます。このように範囲が重なるときは、条件の順序が結果を変えます。元の並びなら、Bの枝に進んだ時点で「80以上ではなかった」がすでに成立しているため、Bは60以上80未満を表します。条件式に上限が見えなくても、前の枝を通らなかった事実が上限を決めています。

また、elifを別のifに変えると、それぞれ独立に判定する形になります。連続した独立のifは複数の処理を実行できるため、1つのif・elif・elseのまとまりとは別物です。選択肢を1つに絞るのか、該当する処理を複数実行するのか、目的から書き方を決めます。

答え:A

例題3 forの合計をトレース表で追う

1から3までの整数を順に足します。繰り返す回数だけでなく、各回で何を足すのかと、合計をどこに残すのかを確かめましょう。次の出力を求めます。

total = 0
for n in range(1, 4):
    total = total + n
print(total)
  1. 反復の前にtotalを0とします。合計を保存する場所の初期値が必要で、加算する前に何が入っているかを決めます。
  2. rangeから取り出す値を1、2、3と並べます。終了の4は含まないため、反復は3回です。
  3. 各回の加算前と加算後のtotalを記録します。右辺のtotalは加算前の値なので、更新前後を同じ欄で上書きしないようにします。
  4. forの字下げから外れたprintを1回実行します。全反復を終えた合計を表示する位置なので、途中の1や3は表示されません。
回 n 加算前のtotal 加算 加算後のtotal
初期状態 未設定 0 なし 0
1 1 0 0 + 1 1
2 2 1 1 + 2 3
3 3 3 3 + 3 6

図2のように、前の回の加算後の値が、次の回の加算前へそのまま引き継がれます。毎回0に戻るわけではありません。表の1行を「反復1回分」と決めると、縦に読むだけで値の受け渡しを追えます。

図2 加算前後の合計を反復の回ごとに追う表

図2では、nの列がその回に足す値、前・後の列がtotalの変化を示します。最後の「後」にある6が、反復を抜けた後のtotalです。トレース表は変数の一覧だけではなく、いつの値なのかをそろえた記録です。表の見出しを省いて数だけ書くと、nとtotalの取り違えが起きやすくなります。

出力は次のとおりです。

6

totalの初期化をforの中へ入れると、前の回までの合計を失います。合計を蓄える問題では「反復の前で初期化、反復の中で更新、必要に応じて反復の後で表示」という役割分担を確認します。

答え:6

例題4 whileが止まる直前と直後を分ける

合計が6未満の間、次の整数を足し、その整数を1増やします。次の出力と、繰り返し本体の実行回数を求めましょう。条件に使うtotalと、加える数nの両方を記録するのがポイントです。

total = 0
n = 1
while total < 6:
    total = total + n
    n = n + 1
print(total, n)
  1. 初期状態をtotalが0、nが1と書きます。最初の判定も、この初期値で行うからです。
  2. total < 6が真なら、まずtotalに現在のnを足します。命令の順序に従うので、まだ増やしていないnを使います。
  3. nを1増やしてから条件の行に戻ります。条件を再判定する時点では、本体の2つの代入が両方とも終わっています。
  4. totalが6になったら、次の判定が偽になります。その回は本体へ入らず、現在のtotalとnを表示します。
判定の回 判定時のtotal 判定時のn total < 6 実行後のtotal 実行後のn
1 0 1 真 1 2
2 1 2 真 3 3
3 3 3 真 6 4
4 6 4 偽 実行なし 実行なし

出力は次のとおりです。printに2つの値を渡しているため、間に空白が入ります。

6 4

条件の判定は4回、本体は3回です。最後の偽の判定は、止まることを決めるために必要ですが、加算は行いません。また、最後に加えた数は3でも、その後にnを増やしたため、表示時のnは4です。「最後に使った値」と「終了時に残っている値」は一致するとは限りません。

答え:出力は6 4、本体の実行は3回、条件の判定は4回。

つまずきやすいところと直し方

誤り1 「または」の両側に比較を書かない

誤った書き方はx == 1 or 2です。「xが1または2」と日本語の語順のまま縮めたくなりますが、右側はxとの比較ではありません。Pythonでは0でない数の2が真として扱われるため、この式をifの条件にすると、xが1でなくても真と判断されます。見た目が短い式ほど、比較する対象を省いていないか確認が必要です。

正しい書き方はx == 1 or x == 2です。左右をそれぞれ「xは1か」「xは2か」という質問として完成させます。修正後はxに1、2、それ以外の3を入れ、真・真・偽になることを確かめます。通るはずの値だけでなく、通らないはずの値を試すと、不足した比較を見つけられます。

誤り2 rangeの終了を含めて数える

誤った書き方は「1から5までを足したいのでrange(1, 5)」です。どこが違うかというと、rangeの終了値は取り出さないため、並ぶのは1、2、3、4までです。最初と最後の見た目の差だけで判断すると、欲しい5を落としてしまいます。

正しい書き方はrange(1, 6)です。増分が1で開始が終了より小さいこの場合は、終了から開始を引いた6 − 1で5回と確認できます。ただし、その計算をどんなrangeにも当てはめてはいけません。増分が2なら途中の値を飛ばしますし、正の増分で開始が終了以上なら1つも取り出しません。慣れるまでは実際の値を横に並べるのが確実です。負の増分なら減る向きになり、たとえばrange(5, 0, -2)は5、3、1です。

誤り3 whileの条件が変わる処理を落とす

誤った書き方は、nを1にしてwhile n <= 3:の中でnを表示するだけにする形です。どこが違うかというと、nを変える命令がないので、何周しても条件は真のままです。ここで扱うように途中で抜ける処理もなければ、終了せずに繰り返す無限ループになります。whileは自動的にnを増やす命令ではありません。

正しい書き方は、表示の後、本体の中でn = n + 1を実行する形です。この場合、nが1、2、3のときに本体へ入り、nが4になると次の判定で抜けます。更新を字下げの外へ出すと、繰り返しが終わるまで更新に到達できないので、同じ問題が残ります。

図3のように、条件へ戻る道に値の更新が含まれているかを見ます。この図は例題4に対応し、加算とnの更新を1つの箱にまとめています。偽の道は更新を通らず終了へ向かいます。

図3 条件を先に調べ更新後に再判定する反復の流れ

図3の戻り道を指で1周なぞり、その間に条件へ影響する値がどう変わるかを言葉にします。単に更新があれば必ず終了するわけではありません。たとえばnが3以下の間にnを減らし続けると、上限を超える方向へ進みません。初期値、続ける条件、更新の向きの3つを組にして、いずれ条件が偽になるかを調べます。

練習問題

練習1 範囲の内側と外側を判定する

xが9、10、20、21のそれぞれの場合について、条件Aを10 <= x and x <= 20、条件Bをx < 10 or x > 20とします。AとBの真偽を答え、さらにnot (10 <= x and x <= 20)がAとBのどちらと一致するかを答えましょう。境界の10と20を飛ばさず、4つの値を別々に判定してください。

練習2 表示位置と合計を確かめる

次のプログラムの出力を求めましょう。本体の実行回数と、printの実行回数も答えてください。値を取り出す範囲と、字下げの深さの両方を確かめます。

total = 0
for n in range(2, 7, 2):
    total = total + n
    print(total)

練習3 停止する値を予想する

次のプログラムの出力、本体の実行回数、条件の判定回数を答えましょう。xが10ちょうどになると決めつけず、各回の値を順に書いてください。

x = 1
while x < 10:
    x = x + 3
print(x)

答えと解説

練習1の答えは次の表です。Aの範囲の内側ではBが偽、外側ではBが真になるので、not (10 <= x and x <= 20)はBと一致します。範囲外の式で10以下や20以上にしてしまうと、境界まで外側に含める誤りになります。

x A B
9 偽 真
10 真 偽
20 真 偽
21 偽 真

練習2の答えは、次の3行です。本体は3回、printも3回です。nは2、4、6と変化し、totalは0から2、6、12へ変わります。printが本体の中にあるので、それぞれ加算を済ませた直後の合計を表示します。

2
6
12

練習3の答えは、出力が10、本体が3回、判定が4回です。判定時のxは1、4、7、10となり、最初の3回だけ条件が真です。10のときは偽なので加算せず、現在の値を表示します。

10

この練習では結果が10になりましたが、whileの条件は「10にそろえる命令」ではありません。同じ条件で1から4ずつ増やせば、1、5、9を経て13で止まります。条件は次の処理へ入るかどうかを決めるだけで、更新後の値を上限以内へ修正する働きはありません。

次の単元へのつながりと家庭での確かめ方

次にリストの値を順に調べるときは、forで値を取り出し、ifで必要なものを選びます。最大値を探す、条件に合う個数を数える、複数の値を合計する、といった処理は今回の組み合わせです。関数を学ぶと、ひとかたまりの処理に名前を付け、何度も呼び出せるようになります。その中でも、どの行が実行されるかと、変数の現在値を追う力は変わらず必要です。

家庭での5分の確認は、次の2通りから1つを選べます。いずれも、実行前に予想を書き、結果と違ったら最初にずれた行へ戻る形で行います。

保護者がお子さまと確かめるなら、答えの数値を先に聞くより、「その値は何行目を実行した後のものか」と尋ねると、説明が具体的になります。個別指導で確かめる際も、反復回数の公式から始めず、代入1回の右辺と左辺、条件式の境界、字下げのまとまりまで戻って、どこで読み違えたかを探します。

まとめ

プログラムの結果が予想と違ったとき、最後の表示だけを眺めても原因は絞れません。分岐なら最初に違う道を選んだ条件、反復なら最初に予想と違う値になった代入を探します。トレース表の途中の行が残っていれば、直すべき場所を具体的に示せます。

白板の前で説明するときは、「3回繰り返したから」からもう一歩進み、「各回にこの値を足し、最後の判定でここから出る」と道筋を示してみましょう。繰り返しを読めた証拠は、最後の答えに加えて、止まる瞬間の変数を説明できることです。

本気になった日が、入塾の日。

お子様の教育、迷ったら「丸投げ」してください。必ず、期待以上の結果で返します。武蔵野で育む、武蔵境で学ぶ。

電話は年中無休。365日、24時間、お電話可能。

お電話 チャットで質問チャット