(教材)12【whileによる反復】
■1. whileの書き方
for文と同様に繰り返しで使われるのがwhile文である.書き方は以下の通り:
code:whileloop書式
while 条件式: ◀◀ セミコロン忘れずに
ループ内ブロック
…………
ループ内ブロック
「条件式が成立している ( =真である ) 限り,ループ内ブロックを繰り返す」 という意味になる.
◀◀日本人にとってはforより直感的かもしれない
★実習★while文を使った典型的なプログラムを示すので,入力して動作を確認しなさい.
ファイル名はlesson12-01.py
※#より右は不要
code:lesson12-01.py
import random # ◀◀ ランダム関数を使うのでこいつをimport
i="" # ◀◀ iを空にしておく
while i == "": # ◀◀ iが空ならずっとループ
print( "%d" % random.randint( 1,6 )) # ◀◀サイコロを振る! i=input( "Enter to Continue: " ) # ◀◀ Enterで続行.他で終了
※これはサイコロを1回振るだけを何度でも繰り返すだけ.
#なんの面白みもなくて面目ない……
★実習★下の記事を読み,サンプルを入力して確認しなさい.
かなりの行数があるのでUnixのエディタで編集すること.ファイル名は自由.
ファイル名はlesson12-02.py
追加仕様(1):名前入力時にwhileループが何周目かを示す番号付きで名前を表示
「( 1 )名前?」という表示.()の中が増えていく
※Hint: カウンタ変数 cnt を追加して利用する
↑↑ 変数名はcntでなくてもいい
追加仕様(2):名前入力時,なにも入れずにEnterだけだと終了 ( break )する
※Hint: 2行目の次に何かを追加すればよいはず
★参考の為に,lesson6-01.pyを再掲しておく.
code:lesson6-01.py
while True:
name=input("名前?:")
number=eval(input("回数?:"))
for i in range(number):
if i%3==0:
print("Hello, %s." % name)
elif i%3==1:
print("\tHey, %s!" % name)
else:
print("\t\tHello, World!!!")
■2. whileとforの関係
実は,for文とwhile文は相互変換可能.書き方が違うだけで同じことができる.
例(1):上のプログラムlesson12-01.pyをfor文で書き換えると次のようになる.
code:lesson12-03.py
for i in l:
l.append(i+1)
a=input("Enter to Continue: ")
if a != "": break
★実習★ 上のプログラムを作成し,実行して確認しなさい.
ファイル名は,lesson12-03.py
code:lesson11-01.py
for i in range( 10 ):
print( "%dはい!" % ( i+1 ), end="" )
print( "" )
これをwhileで書き換えると ▼▼ になる.
code:lesson12-04.py
i=0
while i < 10:
print( "%dはい!" % ( i+1 ), end="" )
i=i+1
print( "" )
★実習★ 上のプログラムを作成し,実行して確認しなさい.
ファイル名は,lesson12-04.py
(解説)
lesson12-03.py を見ると,条件分岐にやや面倒なことをしている.
lesson12-04.py では,10回繰り返すだけだが,iを初期化し,whileループの中でiをインクリメント(数を増やす)する手間が入っている.この他にも,range()関数の範囲指定やステップ指定がまとめてやりにくい等のデメリットがある.
要するに,for/whileは同じ処理を書くことはできるが,それぞれ適正な使い方があるということ.それぞれの特徴をまとめると,以下のようになろう.
◎for文は回数やデータの範囲が明確なループが得意:
カウンタを自動インクリメント ( 数値を増やす ) してくれる.
whileだと処理ブロックの中でカウンタを明示的にインクリメントする必要がある.
range()関数で範囲指定をしたり,「リスト要素の数だけ全部」など,大括りな記述ができる.
◎while文は複雑な条件や無限ループが得意:
whileの条件文には複雑な論理演算をまとめて記述できる.
forには条件文は記述できないので,ループ処理の中でやる必要がある.
条件文の処理が非常に複雑な場合,とりあえずwhileで無限ループを作っておき,ループ処理の中で条件が合えばbreakするように作ることが可能.
※無限ループでは,例外処理や終了条件を整えないと暴走するリスクがある
対話的に入力を繰り返し待つ場合も無限ループが基本.
※上のプログラムlesson6-01.pyが良い例.
■3. 付録:少しは面白い?サイコロプログラム
lesson12-01.pyはサイコロを1回振るだけのプログラムだった.
面白くなくて申し訳ないので,次のようにプログラムを考えた.
code:lesson12-05.py
import random
cnt=1
while True:
cnt=int(input("How many?( 0=end ): "))
if cnt==0: break
for i in range(cnt):
a=random.randint(1,6)
print('目|出現回数|出現率%')
for j in range(len(val)):
print(F'{j+1:2d}|{valj:8d}|{valj/cnt*100:.3f}') ★実習★オプション:上のプログラムを実際に実行して確認しなさい.
ファイル名は,lesson12-05.py
入力を1000, 10000, ....と変化させて実行してみよう.
※どんな動きをするのかは,やってみてのお楽しみ.面白いプログラムかどうかは,皆さんの判断におまかせする.中学2年程度の知識として確率を知っていれば,それなりに興味は湧くかと思うが…….
★課題:出力された結果から,どんな処理がされたのかを推測してみよう.
プログラムの各行について,何をやっているのか説明してみよう.
ファイル名は,lesson12-05-doc.txt
※ただし提出義務はない
☆動作を理解するヒント☆
※入力数値を100000,...100000000とすごく大きい値にしたら?
→ 大きな数では出力が遅くなる(PCの演算性能による).
参考:藤井のPC(Corei7-3770@3.5GHz)では,1000万回で7.7秒,1億回で1分25秒,10億回で14分49秒かかった.ちなみに出現率は,1億回で小数点1位まで,10億回で小数点2位までしか揃わなかった
★時間を測りたいなら,"time" コマンドを利用するとよいだろう.
※timeコマンドについては自力で調べなさい
timeコマンドで実行するなら,input()を使ったインタラクティブな入力ではないほうがよい.どう改造すればいいか考えてみよう.
コマンド行は以下のようになるだろう.
$ time python3 lesson12-05E.py
改造したプログラムは別名(上の例だとlesson12-05E.py)で保存しておこう
timeコマンドを使わずにpythonプログラム内で計測する方法もある.余裕がある人はそれも調べてみよう.
以上.
2023/7/19