−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
   応用数学II                         1995.6.29/30
  9.乱数を使って賽を振る                   飯島
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

9.0 はじめに

ここ数回にわたって,関数のグラフを描いてきました。関数に関しては,まだ追究する 余地はあるのですが,あまりそればかりやっていると,内容がどんどん高度化してしまう し,他にもコンピュータの使い方はありますから,取り合えず,テーマを変えてみたいと 思います。そこで今回登場するのが,「乱数」です。これは,コンピュータでシミュレー ションを行う際には不可欠の概念であり,またコンピュータならではの(模擬)実験を行 うための重要な概念です。

9.1 乱数とは

 乱数というのは,数学的には,確率論的な話題です。数学的な詳しいことは,鈴木先生 の授業で聞いてください。応用数学で使うときに必要な乱数の概念としては,          数値を「ランダム」に得たいときに必要なもの という程度の押さえ方でもいいでしょう。(鈴木先生には,「軽薄」と言われそう。)  さて,まずは,次のプログラムを実行してみます。 CLS FOR i = 1 to 100 PRINT USING "#.#####";RND; PRINT ","; NEXT この中の,RND というのが,「乱数」です。このRND という関数は,結果からも分かる ように,0〜1までの値をランダムに出力してくれます。

  9.2 RANDOMIZE TIMER

さて,何回かF5によって実行し,その結果をよく見てください。気がつくことはありま せんか。そう,何回やっても,「 」なんです。これじゃあ乱数とは いうものの,決まりきった系列を引っ張りだしてくることに他ならないと言えます。 そう,そこで,毎回違う系列を使いたいときには,冒頭に, RANDOMIZE TIMER という一行を追加してみましょう。

9.3 コインの表と裏

 ところで,0〜1までの数値が出るだけでは,使い道がないと思う人もいるかもしれま せん。例えば,コイン投げをシミュレーションしたときには,「表」と「裏」が欲しいの にと思うかもしれません。そういうときには,次のように使えます。 CLS FOR i = 1 to 100 coin = RND PRINT USING "#.#####";coin; PRINT " "; IF coin < .5 THEN PRINT "Omote" ELSE PRINT "URA" NEXT 少し表示を考えましょう。 RANDOMIZE TIMER CLS FOR i = 1 TO 100 coin = RND LOCATE 1, 1 PRINT USING "#.#####"; coin; PRINT " "; IF coin < .5 THEN PRINT "Omote" Omote = Omote + 1 ELSE PRINT "Ura" Ura = Ura + 1 END IF PRINT "Total" PRINT "Omote : "; FOR ct = 1 TO Omote PRINT "*"; NEXT PRINT PRINT "Ura : "; FOR ct = 1 TO Ura PRINT "#"; NEXT NEXT

  9.4 サイコロを振る

 これを参考にすると,サイコロを振るというのも, RANDOMIZE TIMER CLS FOR i = 1 TO 100 sai = RND PRINT USING "#.#####"; sai; PRINT " "; SELECT CASE sai CASE IS < 1 / 6: PRINT "1" CASE IS < 2 / 6: PRINT "2" CASE IS < 3 / 6: PRINT "3" CASE IS < 4 / 6: PRINT "4" CASE IS < 5 / 6: PRINT "5" CASE ELSE: PRINT "6" END SELECT NEXT というように書くこともできます。しかし,もっといい手があります。それは, RANDOMIZE TIMER CLS FOR i = 1 TO 100 sai = INT (RND * 6) + 1 PRINT sai; NEXT とする手です。 上の表示と同様に,サイコロの目の出る様子を図示しましょう。結果は6通りあるので, 配列 Result を使って処理することを考えます。すると, RANDOMIZE TIMER DIM Result(6) CLS FOR i = 1 TO 300 sai = INT(6 * RND) + 1 Result(sai) = Result(sai) + 1 LOCATE 1, 1 PRINT sai FOR j = 1 TO 6 PRINT j; FOR k = 1 TO Result(j) PRINT "*"; NEXT PRINT NEXT NEXT

  9.5 二つのサイコロの目の和

 サイコロを一つ振ってもあまり面白味がないので,まずは二つのサイコロの目の和を実 験してみましょう。  要するに,次のようになります。 RANDOMIZE TIMER DIM Result(12) CLS FOR i = 1 TO 300 sai1 = INT(6 * RND) + 1 sai2 = INT(6 * RND) + 1 sum = sai1 + sai2 Result(sum) = Result(sum) + 1 LOCATE 1, 1 PRINT sai1, sai2, sum FOR j = 1 TO 12 PRINT j; FOR k = 1 TO Result(j) PRINT "*"; NEXT PRINT NEXT NEXT  しかし,これでは回数が少ないので,結果があまり信用できません。しかも,回数が多 くなると,画面から出てしまいます。そこで,次のような工夫をしましょう。 RANDOMIZE TIMER DIM Result(12) SCREEN 12 CLS LOCATE 3, 1 FOR j = 2 TO 12 PRINT j NEXT FOR i = 1 TO 3000 LOCATE 1, 1 PRINT i sai1 = INT(6 * RND) + 1 sai2 = INT(6 * RND) + 1 sum = sai1 + sai2 Result(sum) = Result(sum) + 1 FOR j = 2 TO 12 LINE (30, 16 * (j + .3))-(Result(j) + 30, 16 * (j + .8)), , B NEXT NEXT

  9.6 課題(3個への拡張)

 上のプログラムを参考にして,サイコロを3個投げたときの目の和について調べるため のプログラムを作りなさい。

9.7 課題(n個への拡張)

 また,上記の課題が終わり,自信がある人は,n個のサイコロを投げたときの様子を調 べるためのプログラムを作りなさい。               9.6の解答例 : 省略                9.7の解答例(1) SCREEN 12 RANDOMIZE TIMER INPUT "Num of dice"; Num INPUT "Num of Trial"; NumOfTrial DIM sai(Num) DIM Result(6 * Num) Gwidth = 400 \ (Num * 6) Glength = 600 * 3 / (NumOfTrial / SQR(Num)) LOCATE 3, 1 CLS FOR i = 1 TO NumOfTrial LOCATE 1, 1 PRINT USING "#####"; i sum = 0 FOR ct = 1 TO Num sai(ct) = INT(6 * RND) + 1 sum = sum + sai(ct) NEXT Result(sum) = Result(sum) + 1 FOR j = Num TO Num * 6 LINE (30, Gwidth * (j + .3))-(Glength * Result(j) + 30, Gwidth * (j + .8 )), , B NEXT NEXT                9.7の解答例(2) SCREEN 12 RANDOMIZE TIMER INPUT "Num of dice"; Num INPUT "Num of Trial"; NumOfTrial INPUT "Zooming Ratio ( 0-> 1)"; Ratio IF Ratio < .1 THEN Ratio = 1 DIM sai(Num) DIM Result(6 * Num), Probability(6 * Num), OldProbability(6 * Num) Gwidth = 400 \ (Num * 6) Glength = 600 * Ratio LOCATE 3, 1 CLS FOR i = 1 TO NumOfTrial LOCATE 1, 1 PRINT USING "#####"; i sum = 0 FOR ct = 1 TO Num sai(ct) = INT(6 * RND) + 1 sum = sum + sai(ct) NEXT Result(sum) = Result(sum) + 1 FOR j = Num TO Num * 6 Probability(j) = Result(j) / i LINE (30, Gwidth * (j + .3))-(Glength * OldProbability(j) + 30, Gwidth * (j + .8)), 0, B LINE (30, Gwidth * (j + .3))-(Glength * Probability(j) + 30, Gwidth * (j + .8)), , B OldProbability(j) = Probability(j) NEXT NEXT