コンピュータ演習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
No description has been provided for this image

変数を 新しく作る のも、すでにある変数に 入れ直す のも、フローチャートでは同じ 処理(長方形) で表します。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 に代入し表示する」プログラムをフローチャートにすると、次のようになります。

No description has been provided for this image

開始から終了まで、矢印が上から下へ一本道になっています。これが順次の流れです。 このフローチャートを Python のコードにすると、次のようになります。 前回学んだ input/int/print がそのまま対応しています。

In [1]:
# プログラムの開始
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 では上に「入力」「出力」のラベルが付くので見分けられます。

練習: 順次のフローチャートを読む¶

次のフローチャートと同じ動きをするコードを考えます。

  1. 円周率pi に3.14 を入れる
  2. 半径r にinput 関数で値を入力し、整数に変換する
  3. 面積S にr * r * pi を割り当て
  4. 面積S をprint 関数で出力

開始、終了を含めて、どんな記号がどんな順番で並ぶかを紙かツールで描いてみてください。描けたら、対応する Python コードも書いてみましょう。 input() で受け取った値は文字列なので、整数への変換(int)を忘れないでください(フローチャートでも Python でも同じです)。

順次の例: 乱数を作る(random.randint)¶

第03回では、Python で乱数を作るのに random.randint を使いました。フローチャートでも、Python とまったく同じ式 をそのまま書きます(Flowchart Maker は Python と同じ書き方が使えます)。

例えば、学籍番号後半5 桁 sid に乱数を足せば、sid 周辺の乱数を生成することができます。以下の例ではsid - 200 ~ sid + 200 の範囲で乱数を生成しています。

No description has been provided for this image
  • 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 と出力する例を、フローチャートにしてみます。

No description has been provided for this image

ひし形の True の側だけに処理があり、False の側は何もせずに合流して終了へ進みます。これは前回書いた、次のコードと同じ流れです。

In [2]:
sid = 61250            # 学籍番号後半5 桁(整数)
if sid % 2 == 0:       # 2 で割った余りが 0 か(ひし形の条件)
    print("even")      # 条件が成り立つ(True)ときだけ実行
even

4.2 if...else(二股に分ける)¶

次は if...else です。条件が成り立つとき(True)と成り立たないとき(False)で、それぞれ別の処理 をします。sid が偶数なら even、奇数なら odd と出力する例です。

No description has been provided for this image

ひし形から流れが二股に分かれ、どちらかの処理を通ってから、また1 本に 合流 して終了へ進みます。対応するコードは次のとおりです。

In [3]:
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 と出力する例です。

No description has been provided for this image

1 つ目のひし形が False のとき、次のひし形へ進みます。上から順に判断していき、最初に True になった枝だけを通る といった感じで、これは前回学んだ「最初に真になったブロックだけが実行される」と、まったく同じ仕組みです。対応するコードは次のとおりです。

In [4]:
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 のコードとフローチャートは、次のように対応しています。コードをフローチャートに直すときは、この対応を順番にあてはめていけば大丈夫です。

  1. いちばん上に 開始(端子)、いちばん下に 終了(端子)を置く。
  2. input は 入力、print は 出力(どちらも平行四辺形)にする。
  3. 変数に値を入れる計算(s = a + b など)は 処理(長方形。「変数・値」ブロック)にする。
  4. if / elif は 判断(ひし形)にして、True(成り立つ)と False(成り立たない)で流れを分ける。and / or でまとめた条件も、1 つのひし形に書ける。
  5. 上から順に 流れ線(矢印)でつなぐ。分かれた流れは、最後に 合流点(白い丸)でまとめる。

逆に、フローチャートが描けていれば、各記号をこの対応にしたがって Python に翻訳するだけで、コードが書けます。フローチャート → コード の順で進めるのが、この授業のおすすめの取り組み方です。

練習: 大小ゲームをフローチャートにする¶

前回の最後に作った「大小ゲーム」を、フローチャートにしてみましょう。流れは次のとおりです。

  • CPU の数を乱数で決める(処理)。
  • あなたの数を入力する(入力)。
  • あなたの数が CPU より大きければ Win、小さければ Lose、同じなら Draw と出力する(判断 → 出力)。

判断(ひし形)を2 つ使う、if...elif...else の形になります。

6. 論理演算子(複数条件の組み合わせ)¶

ここまでは、ひし形(判断)1 つにつき条件を1 つだけ書いてきました。ここからは、「61200 以上 かつ 61300 以下」のように、複数の条件を組み合わせる 方法を学びます。これには 論理演算子(and / or / not)を使います。

例として、学籍番号後半5 桁を sid とし、「sid が 61200 以上 かつ 61300 以下か」(ある範囲に入っているか)を判定したいとします。いまの知識だと、if を入れ子にして次のように書くことになります。

In [5]:
sid = 61250
if sid >= 61200:        # まず下限を確認
    if sid <= 61300:    # 下限を満たしたら、さらに上限を確認
        print("範囲内")
    else:
        print("範囲外")
else:
    print("範囲外")
範囲内

これをフローチャートにすると、ひし形が 2 つ縦に並んだ 形になります。

No description has been provided for this image

動きはこれで正しいのですが、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 で確かめてみましょう。

In [6]:
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 つにまとめられます。

In [7]:
sid = 61250
if (sid >= 61200) and (sid <= 61300):    # 1 つの条件式にまとまった
    print("範囲内")
else:
    print("範囲外")
範囲内

フローチャートも、ひし形が 1 つ になります。

No description has been provided for this image

なお、論理演算子の表し方はプログラミング言語によって異なります。 Python では、かつ をand と表現しますが、C 言語やJava では&& と書きます。 この授業のフローチャートツール(Flowchart Maker)では、条件式を Python と同じ書き方 でそのまま書けるので、and を使います。

上の「ひし形2 つ」のフローチャートと、この「ひし形1 つ(and)」のフローチャートは、まったく同じ動き をします。and を使うと、入れ子になっていた判断を1 つにまとめて、見通しよく書けるのです。

練習: 範囲に入っているか(and)¶

学籍番号後半5 桁を sid に代入し、「sid が 61000 以上 かつ 偶数なら 該当、そうでなければ 非該当」と表示するプログラムを、and を使った if...else で書いてください。偶数の判定は sid % 2 == 0 です。

In [ ]:
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 か、を判定してみます。

In [8]:
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 に使うと、次のように書けます。

In [9]:
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 です)。

No description has been provided for this image

練習: どちらかに当てはまるか(or)¶

学籍番号後半5 桁を sid に代入し、「sid が 61100 未満 または 61200 より大きい(=範囲の外)なら 範囲外、そうでなければ 範囲内」と表示するプログラムを、or を使った if...else で書いてください。

In [ ]:
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 で確かめてみましょう。

In [10]:
sid = 61251
print(sid % 2 == 0)          # sid は偶数か

print(not (sid % 2 == 0))    # sid は偶数でない(= 奇数)か
False
True

sid が奇数のときは、sid % 2 == 0 が False、not でひっくり返って True になります。 not を付ける条件は、どこまでを否定するのかをはっきりさせるため、丸かっこ ( ) でくくる と読みやすくなります。

In [11]:
sid = 61250
if not (sid % 2 == 0):
    print("odd")
else:
    print("even")
even
No description has been provided for this image

なお、not (sid % 2 == 0) は sid % 2 != 0 と書いても同じ意味です。not は、すでにある条件をそのまま否定したいときに便利です。

5.4 and / or / not を組み合わせる¶

and / or / not は、組み合わせて使うこともできます。ただし、混ぜて使うときは どこから先に計算されるか(優先順位)に注意が必要です。論理演算子は、not → and → or の順に強く結びつきます(+ より × が先に計算されるのと似ています)。

優先順位を覚えるのが不安なときは、丸かっこ ( ) で、まとめたいところを囲む のが確実です。かっこがあれば、その中が先に計算されます。読み手にも意図が伝わるので、迷ったらかっこを付けましょう。

In [12]:
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 だけを扱う代数系、ブール代数 において非常に重要な性質です。

練習: 範囲とパターンで分類する¶

Python コード¶

学籍番号後半5 桁を sid に代入し、次のように表示するプログラムを if...elif...else で書いてください。 各条件に and や or を使います。

  • sid が 61100 以上 かつ 61200 以下なら、範囲内 と表示する。
  • そうでない場合で、sid の1 の位が 0 または 5 なら、範囲外だが末尾は 0 か 5 と表示する。
  • それ以外なら、その他 と表示する。
In [18]:
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 を使ってすっきり表しましょう。