Python 3 で数学を。

Python 3 とライブラリで数学の問題を解いていきます。統計学や機械学習はときどき。

Python (Python 3) で数学をやるにはどうしたらいいか。その7. 2重 (多重) ループを理解する。"お前、凄い計算できるんだな! 俺なんか指10本で数えるのがやっとなんだぜ"

このシリーズの過去記事は以下にまとめてある

py3math.hatenablog.com

当記事について

当ブログ筆者も、Python で数学をやるにはどうしたらいいか悩んでいた時期があるから、昔の自分に向けて書いたような記事。

対象とする読者

Python の入門書を一冊か二冊、一通りやった人で、Python の基本的な構文や基本的な用語がだいたいわかっている人。

そして、公式サイトを読む努力をちゃんとする人。

2重 (多重) ループを理解しよう

今回は、簡単な九九表を作成することで 2 重 (多重) ループを理解していく (九九表を作成することが目的なのではなく、ループ処理の理解が目的)。

なるべく丁寧な日本語でコードを説明するよう心掛けるが、当ブログで何度も書いているように、コードを日本語で完璧に説明することは極めて難しい。おおまかにはそうなんだろう、くらいに思ってほしい。

では、いきなりだが、簡単な九九表作成のプログラム例を示そう (九九表といってもいろいろな形式があるが)。

(以下、当記事の Python コードはすべて対話モードで書き、プログラムは 1 例)。

>>> for i in range(1, 10):
...     for j in range(1, 10):
...         print('{:3}'.format(i*j), end='')
...     print('')
...
  1  2  3  4  5  6  7  8  9
  2  4  6  8 10 12 14 16 18
  3  6  9 12 15 18 21 24 27
  4  8 12 16 20 24 28 32 36
  5 10 15 20 25 30 35 40 45
  6 12 18 24 30 36 42 48 54
  7 14 21 28 35 42 49 56 63
  8 16 24 32 40 48 56 64 72
  9 18 27 36 45 54 63 72 81

上のコードを眺めたとき、すぐに何をやっているかわかるだろうか。

for 文はひとつだけなら理解はそう難しくないはずだ (こういう仮定で話を進めるから、for 文が理解できないと当記事は辛いものになると思う)。

上のプログラムの for 文のところだけをまずはよく読んでみよう。

>>> for i in range(1, 10):
...     for j in range(1, 10):

これを日本語で説明する前に print() を差し込んでみよう (print デバッグ)。

長い出力になるがざっと眺めてみてほしい。

>>> for i in range(1, 10):
...     print('i: ', i)
...     for j in range(1, 10):
...         print('j: ', j)
...
i:  1
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  2
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  3
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  4
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  5
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  6
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  7
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  8
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9
i:  9
j:  1
j:  2
j:  3
j:  4
j:  5
j:  6
j:  7
j:  8
j:  9

何らかの規則性は見つかっただろうか。

長すぎて読むのが大変で、規則性を見つけるのが困難かもしれない。

では、range()range(1, 10)range(1, 4) にして出力してみよう。

問題を小さくして考えよう。

>>> for i in range(1, 4):
...     print('i: ', i)
...     for j in range(1, 4):
...         print('j: ', j)
...
i:  1
j:  1
j:  2
j:  3
i:  2
j:  1
j:  2
j:  3
i:  3
j:  1
j:  2
j:  3

これをもう少し読みやすくしよう。

>>> for i in range(1, 4):
...     print('i: ', i)
...     for j in range(1, 4):
...         print('j: ', j)
...     print('')
...
i:  1
j:  1
j:  2
j:  3

i:  2
j:  1
j:  2
j:  3

i:  3
j:  1
j:  2
j:  3

これで少しは読みやすくなっただろう。

日本語で説明しよう。

順に:

変数 i が 1 のとき、1 が出力され、変数 j が 1, 2, 3 と出力される。

変数 i が 2 のとき、2 が出力され、変数 j が 1, 2, 3 と出力される。

変数 i が 3 のとき、3 が出力され、変数 j が 1, 2, 3 と出力される。

これが出力内容の日本語的意味だ。

上を、range(1, 10) の場合に適用しよう。

変数 i が 1 のとき、1 が出力され、変数 j が 1, 2, 3, 4, 5, 6, 7, 8, 9 と出力される。

変数 i が 2 のとき、2 が出力され、変数 j が 1, 2, 3, 4, 5, 6, 7, 8, 9 と出力される。

変数 i が 3 のとき、3 が出力され、変数 j が 1, 2, 3, 4, 5, 6, 7, 8, 9 と出力される。

これを 9 まで繰り返している。

理解できただろうか。

できない場合、自分なりに print() を差し込んだり、自分なりの日本語で解釈してみよう。

他人の日本語は難しいものだから。

それに解釈というものは人それぞれだ。

もう一度、プログラム例全体と出力を示す。

>>> for i in range(1, 10):
...     for j in range(1, 10):
...         print('{:3}'.format(i*j), end='')
...     print('')
...
  1  2  3  4  5  6  7  8  9
  2  4  6  8 10 12 14 16 18
  3  6  9 12 15 18 21 24 27
  4  8 12 16 20 24 28 32 36
  5 10 15 20 25 30 35 40 45
  6 12 18 24 30 36 42 48 54
  7 14 21 28 35 42 49 56 63
  8 16 24 32 40 48 56 64 72
  9 18 27 36 45 54 63 72 81

これの print('{:3}'.format(i*j), end='') はどういう意味なんだろうか。

まず、print('{:3}'.format(...), ...){:3} で表示桁数を指定している。

print('{:3}'.format(...), end='')end='' で改行させないことを指定している。

いちばん重要なのが .format() 内にある i*j だ。

上でしたこの説明を思い出してほしい。

"変数 i が 1 のとき、1 が出力され、変数 j が 1, 2, 3, 4, 5, 6, 7, 8, 9 と出力される。"

つまり、変数 i が 1 のとき、1*1, 1*2, 1*3, 1*4, 1*5, 1*6, 1*7, 1*8, 1*9 の計算結果が出力されるというわけだ。

そして、その出力が終わると、print('') が実行され、1 回の空文字 (空文) 改行が行われる。

変数 i が 2 のときも同じく、2*1, 2*2, 2*3, ..., 2*9

1 2 3 4 5 6 7 8 9 が 出力されると改行。

2 4 6 8 10 12 14 16 18 が出力されると改行。

これが 9 まで続いて終了となる。

以上で、説明は終わりだ。

最後にまたもう一度プログラム例を載せておこう。

>>> for i in range(1, 10):
...     for j in range(1, 10):
...         print('{:3}'.format(i*j), end='')
...     print('')

ぜひこれを弄り回したり、改造しまくって理解してほしい。

(つづく)。