コンピュータ演習II 第04回 フローチャートと論理演算子¶
前回までで、if / if...else / if...elif...else を使った条件分岐を書けるようになりました。プログラムが大きくなってくると、「どんな順番で処理が進むのか」「どこで流れが分かれるのか」を、コードを書く前に整理しておきたくなります。
この回ではまず、処理の流れを図で表す フローチャート を学びます。フローチャートが描けると、プログラムの構造を先に組み立ててから、それを Python のコードに翻訳する、という進め方ができるようになります。
後半では、「61100 以上 かつ 61200 以下」のように 複数の条件を組み合わせる 方法(論理演算子 and / or / not)も学びます。これが使えると、入れ子になっていた if を1 つにまとめて、フローチャートもコードもすっきり書けるようになります。
この回の進め方
このノートブックでは、フローチャートの 読み方、書き方の考え方 を学びます。実際にフローチャートを描く作図ツール(Flowchart Maker)の操作方法は、別に配布する 「Flowchart Maker クイックリファレンス」 にまとめてあります。このノートブックを読んで考え方をつかんでから、ツールで実際に描いてみてください。
1. フローチャートとは¶
プログラムは、書かれた処理を 上から順番に 実行していきます。この「処理の流れ」を、決まった形の図形と矢印で表したものが フローチャート(流れ図)です。
たとえば前回の if...else 文は、「条件が成り立てばこちら、成り立たなければあちら」と流れが分かれます。これを文章やコードだけで追うより、図にした方が、分かれ道の様子が一目で分かります。
フローチャートを描く利点は、おもに次の2 つです。
- コードを書く前に、処理の流れを整理できる。 いきなりコードを書き始めると、条件の抜けや順番の誤りに気づきにくいものです。先に図で流れを組み立てておくと、考えの整理になります。
- 言葉が違っても伝わる。 フローチャートの図形の意味は世界共通なので、Python を知らない人にも処理の流れを説明できます。
この授業では、まずフローチャートで流れを考え、それを Python のコードに翻訳する という順番を大切にします。「構造を考えてから、表記に落とす」習慣を身につけましょう。
2. フローチャートの記号¶
フローチャートでは、処理の種類ごとに 図形(記号) を使い分けます。この授業で使う作図ツール(Flowchart Maker)のどのブロックにあたるかも合わせて示します。以下の図やこの先の図は、すべて Flowchart Maker の見た目に合わせてあります。
| 記号 | 名前 | Flowchart Maker のブロック | 意味 |
|---|---|---|---|
| 角丸の長方形 | 端子(たんし) | 開始 / 終了 | プログラムの 開始 と 終了 |
| 長方形 | 処理 | 変数・値 | 変数に値を入れる、計算する |
| 平行四辺形 | 入出力 | 入力 / 出力 | 値の 入力(input)と結果の 出力(print) |
| ひし形 | 判断 | 条件分岐 | 条件によって流れを 分ける(if 文) |
| 小丸 | 合流 | - | 条件分岐や繰り返しの合流 |
| 矢印 | 流れ線 | True / False |
処理が進む 向き。分岐は True / False |
変数を 新しく作る のも、すでにある変数に 入れ直す のも、フローチャートでは同じ 処理(長方形) で表します。Flowchart Maker では、どちらも 「変数・値」ブロック です。Python の = と同じ感覚で使えます(第02回で学んだとおり、Python では変数を宣言せずにそのまま代入できました。フローチャートも同じです)。
このうち、条件分岐は ひし形(判断) です。ひし形には条件を書き、その条件が成り立つか / 成り立たないかで、流れを2 方向に分けます。Flowchart Maker では、成り立つ側の矢印に True、成り立たない側の矢印に False と表示されます。これは前回学んだ真偽値の True / False そのものです。
Flowchart Maker でフローチャートにブロックを足すときは、記号の間にある + を押して種類を選びます。種類と意味の対応は次のとおりです。今回の演習で使うのは 変数・値、出力、入力、条件分岐 です(for 繰り返しは、繰り返しを学ぶ第06回から使います)。
| ブロック | 意味 |
|---|---|
| 変数・値 | 変数への代入、式の実行(例: total に 0) |
| 出力 | print(...) で結果を表示 |
| 入力 | input(...) の結果を変数へ代入 |
| 条件分岐 | 条件により処理を分ける(if 文。「分岐を追加」で elif も作れる) |
| for 繰り返し | 指定した範囲やリストを繰り返す(第06回から使います) |
3. 順次(じゅんじ)¶
まずは、流れが分かれない、いちばん単純な形から見てみましょう。処理を上から下へ一直線に進めることを 順次 といいます。
例として、「係数a に入力された整数x をかけて変数f に代入し表示する」プログラムをフローチャートにすると、次のようになります。
開始から終了まで、矢印が上から下へ一本道になっています。これが順次の流れです。
このフローチャートを Python のコードにすると、次のようになります。
前回学んだ input/int/print がそのまま対応しています。
# プログラムの開始
a = 2 # 係数を用意する
x = int(input()) # 入力(input 関数)を整数に変換する
f = a * x # 計算した結果を f に入れる
print(f) # 出力(print 関数)
# プログラムの終了
6
ここでは例として、入力した数x をa 倍して出力する(a は 2)、という小さなプログラムを考えます。開始から終了まで、上から下へ一本道に進みます(これが順次です)。
それぞれのブロックは、次のように対応しています。
処理(長方形
a = 2)
これから使う係数を用意します。入力(平行四辺形
x = input())
input()でxに値を受け取ります。処理(長方形
x = int(x))
受け取った文字列を整数に変換します(input()の結果は文字列でした。第03回)。Python ではx = int(input())と1 行にまとめて書けます。処理(長方形
f = a * x)
計算した結果を、変数fに入れます。出力(平行四辺形
print(f))
printでfの値を表示します。
入力と出力はどちらも平行四辺形(入出力の記号)ですが、Flowchart Maker では上に「入力」「出力」のラベルが付くので見分けられます。
練習: 順次のフローチャートを読む¶
次のフローチャートと同じ動きをするコードを考えます。
- 円周率
piに3.14を入れる - 半径
rにinput関数で値を入力し、整数に変換する - 面積
Sにr * r * piを割り当て - 面積
Sをprint関数で出力
開始、終了を含めて、どんな記号がどんな順番で並ぶかを紙かツールで描いてみてください。描けたら、対応する Python コードも書いてみましょう。
input() で受け取った値は文字列なので、整数への変換(int)を忘れないでください(フローチャートでも Python でも同じです)。
順次の例: 乱数を作る(random.randint)¶
第03回では、Python で乱数を作るのに random.randint を使いました。フローチャートでも、Python とまったく同じ式 をそのまま書きます(Flowchart Maker は Python と同じ書き方が使えます)。
例えば、学籍番号後半5 桁 sid に乱数を足せば、sid 周辺の乱数を生成することができます。以下の例ではsid - 200 ~ sid + 200 の範囲で乱数を生成しています。
sid = 61250… 学籍番号後半5 桁を入れる変数(処理)。演習では自分の番号に書き換えます。n = sid + random.randint(-200, 200)…-200〜200の乱数を作ってsidに足す(処理)。nを出力する(出力)。
こうすると n は、sid を中心に -200〜+200 ばらつく数になり、実行のたびに変わります。
4. 分岐(ぶんき)¶
次に、条件によって流れが分かれる 分岐 を見ていきます。分岐には ひし形(判断) を使います。ひし形に条件を書き、その条件が成り立つ方向(True)と成り立たない方向(False)に矢印を分けます。
4.1 if(片方だけ実行)¶
まず、前回の if 文(else なし)です。「条件が成り立つときだけ処理をして、成り立たなければ何もしない」という形でした。学籍番号 sid が偶数のとき even と出力する例を、フローチャートにしてみます。
ひし形の True の側だけに処理があり、False の側は何もせずに合流して終了へ進みます。これは前回書いた、次のコードと同じ流れです。
sid = 61250 # 学籍番号後半5 桁(整数)
if sid % 2 == 0: # 2 で割った余りが 0 か(ひし形の条件)
print("even") # 条件が成り立つ(True)ときだけ実行
even
4.2 if...else(二股に分ける)¶
次は if...else です。条件が成り立つとき(True)と成り立たないとき(False)で、それぞれ別の処理 をします。sid が偶数なら even、奇数なら odd と出力する例です。
ひし形から流れが二股に分かれ、どちらかの処理を通ってから、また1 本に 合流 して終了へ進みます。対応するコードは次のとおりです。
sid = 61250
if sid % 2 == 0:
print("even") # True(偶数)のとき
else:
print("odd") # False(奇数)のとき
even
4.3 if...elif...else(つなげて多分岐)¶
3 つ以上に分けたいときは、ひし形を 数珠つなぎ にします。これが前回の if...elif...else に対応します。変数 a が 10 未満なら small、20 未満なら medium、それ以外なら large と出力する例です。
1 つ目のひし形が False のとき、次のひし形へ進みます。上から順に判断していき、最初に True になった枝だけを通る といった感じで、これは前回学んだ「最初に真になったブロックだけが実行される」と、まったく同じ仕組みです。対応するコードは次のとおりです。
a = 15
if a < 10:
print("small") # 1 つ目のひし形が True
elif a < 20:
print("medium") # 1 つ目が False、2 つ目が True
else:
print("large") # どちらも False
medium
elif を増やせば、ひし形をさらにつなげて、何段階にでも分けられます。
練習: 分岐のフローチャートを描く¶
前回書いた、次のコードをフローチャートにしてみましょう。last の値で low / mid / high の3 つに分ける、if...elif...else です。
last = sid % 10
if last < 3:
print("low")
elif last < 7:
print("mid")
else:
print("high")
ひし形を2 つ使います。4.3 の図を参考に、開始 / 終了 / 判断 / 処理 / 流れ線を並べてみてください。
5. コードをフローチャートに直す手順¶
ここまでの例から分かるように、Python のコードとフローチャートは、次のように対応しています。コードをフローチャートに直すときは、この対応を順番にあてはめていけば大丈夫です。
- いちばん上に 開始(端子)、いちばん下に 終了(端子)を置く。
inputは 入力、printは 出力(どちらも平行四辺形)にする。- 変数に値を入れる計算(
s = a + bなど)は 処理(長方形。「変数・値」ブロック)にする。 if/elifは 判断(ひし形)にして、True(成り立つ)とFalse(成り立たない)で流れを分ける。and/orでまとめた条件も、1 つのひし形に書ける。- 上から順に 流れ線(矢印)でつなぐ。分かれた流れは、最後に 合流点(白い丸)でまとめる。
逆に、フローチャートが描けていれば、各記号をこの対応にしたがって Python に翻訳するだけで、コードが書けます。フローチャート → コード の順で進めるのが、この授業のおすすめの取り組み方です。
練習: 大小ゲームをフローチャートにする¶
前回の最後に作った「大小ゲーム」を、フローチャートにしてみましょう。流れは次のとおりです。
- CPU の数を乱数で決める(処理)。
- あなたの数を入力する(入力)。
- あなたの数が CPU より大きければ
Win、小さければLose、同じならDrawと出力する(判断 → 出力)。
判断(ひし形)を2 つ使う、if...elif...else の形になります。
6. 論理演算子(複数条件の組み合わせ)¶
ここまでは、ひし形(判断)1 つにつき条件を1 つだけ書いてきました。ここからは、「61200 以上 かつ 61300 以下」のように、複数の条件を組み合わせる 方法を学びます。これには 論理演算子(and / or / not)を使います。
例として、学籍番号後半5 桁を sid とし、「sid が 61200 以上 かつ 61300 以下か」(ある範囲に入っているか)を判定したいとします。いまの知識だと、if を入れ子にして次のように書くことになります。
sid = 61250
if sid >= 61200: # まず下限を確認
if sid <= 61300: # 下限を満たしたら、さらに上限を確認
print("範囲内")
else:
print("範囲外")
else:
print("範囲外")
範囲内
これをフローチャートにすると、ひし形が 2 つ縦に並んだ 形になります。
動きはこれで正しいのですが、if を入れ子にするぶん、ひし形が2 つに増え、else も2 回出てきて、少し読みにくいですね。
実際プログラムコードを見てみても、if 文の中にさらにif 文が入れ子になっていて、複雑に見えますね。
今回の場合sid が61200 以上、かつ、sid が61300 以下、と二つの条件があるため、2 回条件分岐する必要がありました。
ここで「両方の条件を同時に満たすか」 を 1 回の条件分岐 で書けると、ずっとすっきりします。
それを可能にするのが論理演算子です。
5.1 and(かつ)¶
and は、2 つの条件が両方とも成り立つとき に真(True)となり、それ以外のときは偽(False)となる論理演算子です。「A かつ B」を A and B と書きます。
A |
B |
A and B |
|---|---|---|
True |
True |
True |
True |
False |
False |
False |
True |
False |
False |
False |
False |
and でつなぐ左右には、これまで if の条件に書いてきた 比較の式(sid >= 61100 など)をそのまま置けます。まずは、and でつないだ式の結果を print で確かめてみましょう。
sid = 61250
print(sid >= 61200) # 下限はクリアしているか
print(sid <= 61400) # 上限はクリアしているか
print((sid >= 61200) and (sid <= 61400)) # 両方を同時に満たすか
True True True
どこまでが一つ目の条件であるかをはっきりさせるため、丸かっこ ( ) でくくる と読みやすくなります
sid が 61250 のときは、下限、上限の両方を満たすので、and でつないだ式も True になります。sid を 61400 などに変えて実行すると、上限を満たさなくなり、and の式は False に変わります。このように、and は 両方が True のときだけ True になります。
ちなみに、これを表で表現すると以下のように書けます。
sid >= 61200 |
sid <= 61300 |
(sid >= 61200) and (sid <= 61300) |
|---|---|---|
True |
True |
True |
True |
False |
False |
False |
True |
False |
False |
False |
False |
この and を if の条件に使うと、上の入れ子の if を、次のように1 つにまとめられます。
sid = 61250
if (sid >= 61200) and (sid <= 61300): # 1 つの条件式にまとまった
print("範囲内")
else:
print("範囲外")
範囲内
フローチャートも、ひし形が 1 つ になります。
なお、論理演算子の表し方はプログラミング言語によって異なります。
Python では、かつ をand と表現しますが、C 言語やJava では&& と書きます。
この授業のフローチャートツール(Flowchart Maker)では、条件式を Python と同じ書き方 でそのまま書けるので、and を使います。
上の「ひし形2 つ」のフローチャートと、この「ひし形1 つ(and)」のフローチャートは、まったく同じ動き をします。and を使うと、入れ子になっていた判断を1 つにまとめて、見通しよく書けるのです。
練習: 範囲に入っているか(and)¶
学籍番号後半5 桁を sid に代入し、「sid が 61000 以上 かつ 偶数なら 該当、そうでなければ 非該当」と表示するプログラムを、and を使った if...else で書いてください。偶数の判定は sid % 2 == 0 です。
sid = 60000 # ← 学籍番号後半5 桁(整数)に書き換えてください
# sid が 61000 以上 かつ 偶数なら 該当、そうでなければ 非該当 と表示する if...else 文を書いてください
5.2 or(または)¶
or は、2 つの条件のどちらか一方でも成り立てば 真(True)となり、両方とも成り立たないときだけ偽(False)となる論理演算子です。「A または B」を A or B と書きます。
A |
B |
A or B |
|---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
True |
False |
False |
False |
例として、sid の1 の位(sid % 10)が 0 または 5 か、を判定してみます。
sid = 61250
last = sid % 10
print(last == 0) # 1 の位は 0 か
print(last == 5) # 1 の位は 5 か
print(((last == 0) or (last == 5))) # どちらか一方でも成り立つか
True False True
こちらも、どこまでが一つ目の条件であるかをはっきりさせるため、丸かっこ ( ) でくくる と読みやすくなります
これも表にしてみましょう。
last == 0 |
last == 5 |
(last == 0) or (last == 5) |
|---|---|---|
True |
True |
True |
True |
False |
True |
False |
True |
True |
False |
False |
False |
sid が 61250 のときは1 の位が 0 なので、last == 0 が True、or の式も True になります。or は どちらか一方でも True なら True です。これを if に使うと、次のように書けます。
sid = 61250
last = sid % 10
if (last == 0) or (last == 5):
print("末尾が 0 か 5")
else:
print("それ以外")
末尾が 0 か 5
これをフローチャートにすると以下のようになります。
なお、or も言語によって書き方が異なり、C 言語やJava では|| と書きます(Flowchart Maker は Python と同じ or です)。
練習: どちらかに当てはまるか(or)¶
学籍番号後半5 桁を sid に代入し、「sid が 61100 未満 または 61200 より大きい(=範囲の外)なら 範囲外、そうでなければ 範囲内」と表示するプログラムを、or を使った if...else で書いてください。
sid = 60000 # ← 学籍番号後半5 桁(整数)に書き換えてください
# sid が 61100 未満 または 61200 より大きいなら 範囲外、そうでなければ 範囲内 と表示する if...else 文を書いてください
5.3 not(〜でない)¶
not は、条件の 真偽をひっくり返す 論理演算子です。not A は、A が True のとき False、A が False のとき True になります。and / or が2 つの条件をつなぐのに対し、not は1 つの条件の前に付けて使います。
A |
not A |
|---|---|
True |
False |
False |
True |
たとえば「sid が偶数 でない」(=奇数)は、not (sid % 2 == 0) と書けます。not の働きを print で確かめてみましょう。
sid = 61251
print(sid % 2 == 0) # sid は偶数か
print(not (sid % 2 == 0)) # sid は偶数でない(= 奇数)か
False True
sid が奇数のときは、sid % 2 == 0 が False、not でひっくり返って True になります。
not を付ける条件は、どこまでを否定するのかをはっきりさせるため、丸かっこ ( ) でくくる と読みやすくなります。
sid = 61250
if not (sid % 2 == 0):
print("odd")
else:
print("even")
even
なお、not (sid % 2 == 0) は sid % 2 != 0 と書いても同じ意味です。not は、すでにある条件をそのまま否定したいときに便利です。
5.4 and / or / not を組み合わせる¶
and / or / not は、組み合わせて使うこともできます。ただし、混ぜて使うときは どこから先に計算されるか(優先順位)に注意が必要です。論理演算子は、not → and → or の順に強く結びつきます(+ より × が先に計算されるのと似ています)。
優先順位を覚えるのが不安なときは、丸かっこ ( ) で、まとめたいところを囲む のが確実です。かっこがあれば、その中が先に計算されます。読み手にも意図が伝わるので、迷ったらかっこを付けましょう。
sid = 61250
# 「61100 以上 かつ 61200 以下」を、かっこでひとまとまりにする
in_range = (sid >= 61100) and (sid <= 61200)
print(in_range)
# 「範囲の外」は、その否定。not でひっくり返せる
print(not in_range)
False True
上の not in_range(範囲の外)は、or を使って sid < 61100 or sid > 61200 と書いても同じ意味になります。「かつ の否定」が「または」に化けるのは少し不思議ですが、こうした言いかえができることも知っておくと便利です(くわしくは発展で扱います)。
余談: ド・モルガンの法則¶
「A かつ B ではない」は「A でない または B でない」と同じ、「A または B ではない」は「A でない かつ B でない」と同じ、という関係があります。これを ド・モルガンの法則 といいます。式で書くと次のとおりです。
not (A and B)はnot A or not Bと同じnot (A or B)はnot A and not Bと同じ
さきほどの not (sid >= 61100 and sid <= 61200) が sid < 61100 or sid > 61200 になるのは、この法則によるものです(sid >= 61100 の否定が sid < 61100、sid <= 61200 の否定が sid > 61200)。
これは0 と1 だけを扱う代数系、ブール代数 において非常に重要な性質です。
sid = 60000 # ← 学籍番号後半5 桁(整数)に書き換えてください
last = sid % 10
# 上の 3 つの分類を if...elif...else で書いてください
フローチャート¶
上記で書いたプログラムを、Flowchart Maker を使ってフローチャートにしてみてください。
5.5 論理演算子の記号について¶
各節で説明したとおり、プログラミング言語によって、論理演算子に用いる記号は異なります。 混乱を避けるためここでまとめておきます。
| 論理演算子 | Python・Flowchart Maker | C 言語 | Java |
|---|---|---|---|
AND |
and |
&& |
&& |
OR |
or |
|| |
|| |
NOT |
not |
! |
! |
まとめ¶
この回では、処理の流れを図で表す フローチャート と、複数の条件を組み合わせる 論理演算子 を学びました。
- 記号:端子(開始 / 終了)、処理(変数・値。変数に値を入れる)、入出力(入力 / 出力の平行四辺形)、判断(条件分岐)、流れ線(
True/False)。図はすべて Flowchart Maker の見た目に合わせてある。 - 順次 / 分岐:順次は上から下への一直線。分岐はひし形(判断)で
True/Falseに分ける。if/if...else/if...elif...elseが、それぞれ図の形に対応する。 - 論理演算子:
and(かつ)は両方が真のとき真、or(または)はどちらか一方でも真なら真、not(〜でない)は真偽を反転。優先順位はnot→and→or、迷ったら丸かっこでまとめる。 - コードとの対応:フローチャートの記号は、そのまま Python の命令に翻訳できる。入れ子だったひし形は、
and/orを使えば1 つにまとめられる。
次回からの演習では、まずフローチャートで流れを考えてから、Python のコードに翻訳する という進め方をしていきます。条件が複雑なときは、and / or / not を使ってすっきり表しましょう。