『モンテカルロ法入門』ExcelVBAソース公開

『モンテカルロ法入門』ExcelVBAソース公開

問題点

本著には以下でマクロ付エクセルがダウンロードできますが、最新のバージョンのエクセルで開くとマクロが全て消えているという問題があります。

きんざいSTORE『モンテカルロ法入門』
※本著に記載されているアドレスと変わっているので注意。現在は上記のリンクが正しいアドレスです

※ソースコードが消えている。「Option Explicit」があるのはデフォルトで記載される設定にしているため

しかも出て来るエラー表示が以下なので「マクロが無効になっているせいか?」と勘違いしてしまいます。※本著に従ってちゃんとマクロを有効にしても以下のエラーが出ます

これはエクセルのバーションが変わり拡張子が変更(xls→xlsm)になった事が原因です。
そして、xlsmに変換してもマクロは消えたままです。
一度開いた時点で消えるので、それから変換しても消えたままなのだと考え、エクセルを開かずにxls→xlsm変換も試しましたがマクロは消えたままでした。

私はマクロを本著の通り手書きする事で対応しましたが、本著で私同様困っている人のためにマクロ部分のソースを公開します。コピペしてご使用下さい。

前準備

ダウンロードした拡張子xlsのエクセルファイルを開いてメニューの「ファイル」→「名前を付けて保存」→拡張子で「Excel マクロ有効ブック(*.xlsm)」を選択→「保存」ボタン押下

新しく出来た拡張子xlsmのエクセルファイルを開く

VBAエディタを開き後述のソースコードを標準モジュールのModule1にコピペする

ソースコード

※自分で記述したのだけ載せています

第3章 モンテカルロ円周率

Option Explicit

Sub モンテカルロ円周率()

    Dim サンプル数 As Long, X As Double, Y As Double
    Dim 原点からの距離 As Double, 円の中の数 As Long
    Dim 推定円周率 As Double, i As Long
    
    Randomize
    
    サンプル数 = Range("C6").Value
    円の中の数 = 0
    
    For i = 1 To サンプル数
        
        X = Rnd()
        Y = Rnd()
        原点からの距離 = Sqr(X ^ 2 + Y ^ 2)
        If 原点からの距離 <= 1 Then 円の中の数 = 円の中の数 + 1
    
    Next i
    
    推定円周率 = 4 * 円の中の数 / サンプル数
    Range("D6") = 推定円周率
        

End Sub

Sub モンテカルロ円周率グラフ()

    Const サンプル数 = 5000
    
    Dim X As Double, Y As Double
    Dim 原点からの距離 As Double, 円の中の数 As Long
    Dim 推定円周率 As Double, i As Long
    Dim 円中RowNo As Integer, 円外RowNo As Integer
    
    Randomize
    Range("B49:E5048").ClearContents
    
    円の中の数 = 0
    円中RowNo = 49
    円外RowNo = 49
    
    For i = 1 To サンプル数
        
        X = Rnd()
        Y = Rnd()
        
        原点からの距離 = Sqr(X ^ 2 + Y ^ 2)
        If 原点からの距離 < 1 Then
            円の中の数 = 円の中の数 + 1
            Cells(円中RowNo, 2) = X
            Cells(円中RowNo, 3) = Y
            円中RowNo = 円中RowNo + 1
        Else
            Cells(円外RowNo, 4) = X
            Cells(円外RowNo, 5) = Y
            円外RowNo = 円外RowNo + 1
        End If
            
        Range("A44") = i
        推定円周率 = 4 * 円の中の数 / i
        Range("A45") = 推定円周率
        
        Application.Wait [Now() + "0:00:00.01"]
        DoEvents    '本書にはなかったがグラフの描画更新(アニメーション)には必要
        
    Next i
    
End Sub

第5章 千鳥足

●基本

Option Explicit

Sub グラフY軸設定(ByVal グラフ番号 As Integer, _
                  ByVal 上限値 As Double, _
                  ByVal 下限値 As Double)

    With ActiveSheet.ChartObjects(グラフ番号) _
        .Chart.Axes(xlValue)
        .MaximumScale = 上限値
        .MinimumScale = 下限値
    End With

End Sub

Sub 千鳥足()

    Const 歩行数 = 30
    
    Dim 道の方向 As Double, アニメーション As Boolean
    Dim 現在地 As Double, Y軸上限値 As Double
    Dim Y軸下限値 As Double, 一様乱数 As Double, i As Integer
    
    Randomize
    
    Range("C39:D68").ClearContents
    
    道の方向 = Range("D31").Value
    アニメーション = Range("D32").Value
    Y軸上限値 = Range("D33").Value
    Y軸下限値 = Range("D34").Value
    
    Call グラフY軸設定(1, Y軸上限値, Y軸下限値)
    
    現在地 = 0
    
    For i = 1 To 歩行数
    
        一様乱数 = Rnd()
        If 一様乱数 <= 0.4 Then     '0.4の確率で右へふらつく
            現在地 = 現在地 + 道の方向 - 1
        ElseIf 一様乱数 <= 0.6 Then '0.2の確率でまっすぐ
            現在地 = 現在地 + 道の方向
        Else                        '0.4の確率で左へふらつく
            現在地 = 現在地 + 道の方向 + 1
        End If
            
        Cells(38 + i, 3) = i
        Cells(38 + i, 4) = 現在地
        
        If アニメーション Then
            '速すぎないように、一歩ごとに0.5秒間ストップする
        Application.Wait [Now() + "0:00:00.05"]
        DoEvents    '本書にはなかったがグラフの描画更新(アニメーション)には必要
        End If
        
    Next i
    
End Sub

●泥酔

Sub グラフXY設定(ByVal グラフ番号 As Integer, _
                 ByVal X上限値 As Double, _
                 ByVal X下限値 As Double, _
                 ByVal Y上限値 As Double, _
                 ByVal Y下限値 As Double)

    With ActiveSheet.ChartObjects(グラフ番号) _
        .Chart.Axes(xlCategory)
        .MaximumScale = X上限値
        .MinimumScale = X下限値
    End With
    
    With ActiveSheet.ChartObjects(グラフ番号) _
        .Chart.Axes(xlValue)
        .MaximumScale = Y上限値
        .MinimumScale = Y下限値
    End With

End Sub

Sub 泥酔千鳥足()

    Const 歩行数 = 1000
    
    Dim 道の方向 As Double, アニメーション As Boolean
    Dim 現在地X As Double, 現在地Y As Double
    Dim X軸上限値 As Double, X軸下限値 As Double
    Dim Y軸上限値 As Double, Y軸下限値 As Double
    Dim i As Integer
    
    Randomize
    
    Range("C39:E1038").ClearComments
    
    アニメーション = Range("D30").Value
    X軸上限値 = Range("D31").Value
    X軸下限値 = Range("D32").Value
    Y軸上限値 = Range("D33").Value
    Y軸下限値 = Range("D34").Value
    
    Call グラフXY設定(1, X軸上限値, X軸下限値, _
                         Y軸上限値, Y軸下限値)
    
    現在地X = 0
    現在地Y = 0
    
    For i = 1 To 歩行数
    
        Select Case Rnd()   '一様乱数
            Case Is < 0.25: 現在地X = 現在地X - 1   '右へ
            Case Is < 0.5: 現在地X = 現在地X + 1    '左へ
            Case Is < 0.75: 現在地Y = 現在地Y + 1   '前へ
            Case Is < 1: 現在地Y = 現在地Y - 1      '後へ
        End Select
        
        Cells(38 + i, 3) = i
        Cells(38 + i, 4) = 現在地X
        Cells(38 + i, 5) = 現在地Y
        
        If アニメーション Then
            '速すぎないように、一歩ごとに0.1秒間ストップする
        Application.Wait [Now() + "0:00:00.1"]
        End If
        
    Next i
        
End Sub

ITカテゴリの最新記事