蒙特卡洛模拟投掷硬币以获得某种模式

时间:2016-05-13 14:34:18

标签: excel vba montecarlo probability-theory

受本文的启发:Statistics of Coin-Toss Patterns,我进行了一次蒙特卡罗模拟,用于确定使用Excel VBA投掷硬币以获得特定模式的预期数量。下面的代码是蒙特卡洛模拟,用于抛出一个公平的硬币来获得模式HTH,其中H是头部(1),T是尾部(0)。

  
Sub Tossing_Coin()
    Dim Toss(1000000) As Double, NToss(1000000) As Double, AVToss(1000000) As Double
    t0 = Timer
    Sheet2.Cells.Clear
    a = 0

    For j = 1 To 1000000

        p1 = Rnd()
        If p1 <= 0.5 Then
            Toss(1) = 1
        Else
            Toss(1) = 0
        End If

        p2 = Rnd()
        If p2 <= 0.5 Then
            Toss(2) = 1
        Else
            Toss(2) = 0
        End If

        i = 2
        Do
            p3 = Rnd()
            If p3 <= 0.5 Then
                Toss(i + 1) = 1
            Else
                Toss(i + 1) = 0
            End If

            i = i + 1
        Loop Until Toss(i - 2) = 1 And Toss(i - 1) = 0 And Toss(i) = 1

        NToss(j) = i
        a = a + NToss(j)
        AVToss(j) = a / j
        b = AVToss(j)
    Next j

    MsgBox "The expected number of tossing is " & b & "." _
        & vbNewLine & "The running time of simulation is " & Round(Timer - t0, 2) & " s."
End Sub

程序的输出如下所示:

enter image description here

与文章中显示的结果一致。其他投掷公平硬币的模式也是匹配的。尽管有这些结果,我仍然不确定我写的程序是否正确。当硬币不公平时,我的疑问就出现了,这意味着p1p2p3不等于0.5,因为我没有任何信息来检查它的准确性。我还想知道如何在VBA Excel或R中编写一个高效的程序来执行上面的模拟,如THTHTHTHT,THTTHHTHTTH等更长的模式,它的循环超过1,000,000(可能100,000,000或1,000,000,000),但仍然相当快?有什么想法吗?

2 个答案:

答案 0 :(得分:1)

为了提高效率,可以通过赋予一个折腾位来使用变量的位。然后对于每次投掷,旋转左边的位并在第一个位置添加抛出结果,直到右边的位与模式匹配:

json_encode

请注意,VBA没有位移运算符,但左侧的1位移位与乘以2相同:

pattern "HTH"  : 101
mask for "XXX" : 111

1 toss "H" :       1 And 111 = 001
2 toss "T" :      10 And 111 = 010
3 toss "T" :     100 And 111 = 100
4 toss "H" :    1001 And 111 = 001
5 toss "H" :   10011 And 111 = 011
6 toss "T" :  100110 And 111 = 110
7 toss "H" : 1001101 And 111 = 101  : "HTH" matches the first 3 bits

以下是获得与序列匹配的平均折腾数的示例:

  decimal  9 =   1001 in bits
 9 +  9 = 18 =  10010 in bits
18 + 18 = 36 = 100100 in bits

答案 1 :(得分:0)

您需要一个字符串来存储您想要找到的模式。

然后在每次折腾后将最新结果附加到结果字符串的末尾。

然后检查结果的最后n位是否= = pattern其中n =模式的长度。

如果匹配,则记录投掷数和空白结果字符串,然后再次进行...

您可以在大约20行代码中完成它!希望有所帮助。