Ruby - 正規乱数(ボックス=ミューラー法)!

更新日時:


先日は、正規乱数をボックス=ミューラー法で生成して正規分布を検証する 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. 判定

出力されたヒストグラムを確認してみると、綺麗な山になっているので正規乱数が正規分布になっていると言えるでしょう。


乱数生成回数をもっと増やしたり、乱数生成時の定数を変更してみたりすると、もっと一様になるのではないでしょうか?

以上。

 

Sponsored Link

 

コメントする