Ruby - 正規乱数(ボックス=ミューラー法)!
Updated:
先日は、正規乱数をボックス=ミューラー法で生成して正規分布を検証する C++ によるアルゴリズムを紹介しました。
今日は、同じアルゴリズムを Ruby で実現してみました。
アルゴリズムについては、上記リンクの記事を参照してください。
実際、ほとんど同じです。
以下、Ruby によるサンプルスクリプトです。
0. 前提条件
- Cygwin 1.7.15
- Ruby 1.9.3-p194
1. Ruby スクリプト作成
今回作成した Ruby ソースは以下の通り。
File: rndnum_box_muller.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#! /usr/local/bin/ruby
#*********************************************
# ボックス=ミューラー法法による正規乱数生成
#*********************************************
class RndnumBoxMuller
M = 10 # 平均
S = 2.5 # 標準偏差
N = 10000 # 発生させる乱数の個数
PI = 3.1415926535 # 円周率
SCALE = N / 100.0 # ヒストグラム用スケール
def initialize
@hist = Array.new( M * 5, 0 )
end
def generate_rndnum
0.upto( N - 1 ) do |i|
res = rnd
@hist[res[0]] += 1
@hist[res[1]] += 1
end
end
def display
0.upto( M * 2 ) do |i|
printf("%3d:%4d | ", i, @hist[i])
1.upto( @hist[i] / SCALE ) { |j| print "*" }
puts
end
end
private
def rnd
r_1 = rand
r_2 = rand
x = S * Math.sqrt(-2 * Math.log(r_1)) * Math.cos(2 * PI * r_2) + M
y = S * Math.sqrt(-2 * Math.log(r_1)) * Math.sin(2 * PI * r_2) + M
return [ x.to_i, y.to_i ]
end
end
begin
obj = RndnumBoxMuller.new
obj.generate_rndnum
obj.display
rescue => e
$stderr.puts "[例外発生] #{e}"
end
2. 実行
まず、実行権限を付与。
$ chmod +x rndnum_box_muller.rb
そして、実行。
$ ./rndnum_box_muller.rb
0: 2 |
1: 13 |
2: 48 |
3: 113 | *
4: 298 | **
5: 609 | ******
6:1178 | ***********
7:1954 | *******************
8:2701 | ***************************
9:3205 | ********************************
10:3032 | ******************************
11:2614 | **************************
12:1892 | ******************
13:1167 | ***********
14: 669 | ******
15: 327 | ***
16: 127 | *
17: 36 |
18: 11 |
19: 2 |
20: 1 |
3. 判定
出力されたヒストグラムを確認してみると、綺麗な山になっているので正規乱数が正規分布になっていると言えるでしょう。
乱数生成回数をもっと増やしたり、乱数生成時の定数を変更してみたりすると、もっと一様になるのではないでしょうか?
以上。
Comments