−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
応用数学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