| Top Page | プログラミング | Perl 目次 | prev | next | 索引 |

3. 関数を使う:rand を利用してランダムなパターンを生成する

関数と引数

ここまでのプログラム例に,何度か print という語がでてきました. print の後ろに変数名を書くと,その変数の値を画面に表示してくれました. printのように,名前を呼べば決まった処理を賢くやってくれるものを Perl では関数と言います.多くの関数はなんらかのパラメータを受けとり, それに応じた処理を行います.関数に渡すパラメータは,引数(ひきすう)と 呼ばれます.

print 関数は,表示したい変数を引数として受けとります. 引数は,() で囲むのが基本ですが,囲まなくても Perl の処理系が誤解 なく解釈できる場合には () を省略することもできます. これまでの例では, print の後の () は省略していました.

Perl にはたくさんの関数が用意されています.今度は rand という関数を 使ってみます.rand は名前から想像されるように乱数を返す関数です. rand() のように引数になにも指定しないと,[0, 1.0) ,すなわち 0 以上,1 未満 の数値を返します([ は閉区間すなわち境界値を含み,) は開区間すなわち境界値 を含まない).

前のページで説明した for 文を使って,乱数を 10 回表示するプログラムを 書いてみます.

for ($i = 0; $i < 10; ++$i) {   #  ++ は,値を1だけ増やす演算子
    print rand(), "\n";         #   "\n" は改行.
}

値を1増やす,という命令を $i = $i + 1 よりも短く書くために, ++ という演算子を使っています.これは値を1増やすための専用の演算子 です.値を1だけ減らすのは,当然想像されるように -- です.

rand 関数と条件判断とを使って,おみくじプログラムを書いてみましょう.

# 運試しプログラム.

$x = rand();

if ($x < 0.05) {
    print "Very, very lucky.\n";
}
elsif ($x < 0.15) {
    print "Very lucky.\n";
}
elsif ($x < 0.4) {
    print "Lucky.\n";
}
else {
    print "Hm...\n";
}

<練習>


ランダムな天気の系列を作ってみる

変数の使い方,関数 rand の使い方,for を使った繰り返し,条件判断と, これだけの知識があればランダムなパターンを作るプログラムがいろいろ 書けます. たとえば,晴れ,曇り,雨の確率を与えてランダムな天気系列を作るプログラムを 書いてみます.

# ランダムな天気系列を生成するプログラム.

$days = 100;  # 全部で何日の天気を生成するか.
$prob_fine = 0.3;      # 晴れの日の確率
$prob_overcast = 0.5;  # 曇りの日の確率
$prob_rainy = 0.2;     # 雨の日の確率

if ($prob_fine + $prob_overcast + $prob_rainy != 1.0) {  # 足して1かチェック
    print "Sum of probabilities should be 1.0\n";
    exit();    #  プログラムの実行を終了させる関数.
}

for ($i = 0; $i < $days; ++$i) {    #  日数分,繰り返す.

    $x = rand();                    #  rand ()は0以上1未満の乱数を返す.

    if ($x <= $prob_fine) {         # 乱数の値によって天気を決める.
        print $i + 1, "\tfine\n";   # 日と天気(fine)を表示する.\tはタブ.
    }
    elsif ($x <= ($prob_fine + $prob_overcast)) {
        print $i + 1, "\tovercast\n";  # 日と天気(overcast)を表示する.
    }
    else {
        print $i + 1, "\trainy\n";    # 日と天気(rainy)を表示する.
    }
}

このプログラムを実行すると,日(1から)と天気がずらずらと表示されます. fine や rainyという文字列を表示させるかわりに, それぞれの天気の日の日射量だの降水量だのを代わりに表示してもよいでしょう. WindowsでのPerlの実行 のところで説明したリダイレクトを使えば,この出力をファイルに書き込むことが できます.

プログラムのはじめのほうでは,exitという関数を使っています. これはプログラムの実行を終了する関数です.その後にいくらプログラムが続いていても, exit 関数を呼び出したらそこで終了です. 上の例では,各天候状態の確率の合計がちゃんと 1.0 になってるかをチェックして, なってなかったら不正なデータだからそこで終了,というふうに使われています. 確率の値をいじっていると,合計が 1.0 にならないように誤った確率を与えて しまうことはままあるでしょう.人は必ずまちがえます (>プログラムのまちがい,データのまちがい). プログラム中で簡単にまちがいのチェックができるなら,ぜひやってもらいましょう.

上のプログラムを weather.pl という名前のファイルにしまったとして, 天気ファイルを作ってみましょう.

 perl weather.pl > weather.txt 

とすれば,weather.txt にランダムな天気系列が書き込まれます. なんとなく,シミュレーションっぽい感じがしてきましたね.

<練習>


ランダムにばらつく点を作ってみる

こんどは2次元平面上にランダムに点を分布させるプログラムを書いてみます. 野外で観測した生き物の分布がランダムなものかどうかを検討するときの比較, といった使い方ができるでしょう (点の分布パターンの解析については,たとえば 点過程の解説ページ などを見てください).

#  四角形内のランダムな点の分布パターンを生成するプログラム

$points = 100;  # 点の数
$max_x = 50;    # x軸方向の長さ
$max_y = 40;    # y軸方向の長さ

for ($i = 0; $i < $points; ++$i) {    #  点の数だけ繰り返す.

    $x = rand();         #  rand ()は0以上1未満の乱数を返す.
    $y = rand();         #  ( 呼ぶたびに違う値を返す)

    $x = $x * $max_x;     #  [0, 1) の範囲の値を [0, $max_x)の範囲の値へ.
    $y = $y * $max_y;     #  [0, 1) の範囲の値を [0, $max_y)の範囲の値へ.

    printf "%.2f\t%.2f\n", $x, $y;    # $x, $y それぞれ小数点以下2ケタまで表示.
}

読めば分かるプログラムですが,最後の printf は新しい関数です. print のうしろの f は,format の f で,書式指定をして出力するための 関数です.

printf の直後の文字列が書式を指定する文字列,そのうしろに 出力したいものを並べます.文字列中に複数の書式指定がある場合,最初の 指定は最初の変数の出力を指定し,2番めの指定は次の変数の出力に, というふうに順番に適用します.

おもな書式指定をあげておきます.

<練習>

自分で工夫していろいろなプログラムを書いたり, その出力をグラフにしたりしてみましょう.

プログラミング言語というのはいわば素材です. 単純な素材をどう組み合わせたら目的を達成することができるのか, よく考え,工夫する努力を惜しまないことが大切です. 自分で工夫する手間を惜しんでいると,いつになっても自立できません.



| Top Page | プログラミング | Perl 目次 | prev | next |