Excel VBA的Rnd()真的很糟糕吗?

XYZ*_*XYZ 13 random vba excel-vba montecarlo excel-2013

我需要一个用于2D蒙特卡罗模拟的伪随机数生成器,它没有使用简单LCG获得的特征超平面.我使用以下代码在Excel 2013中测试了随机数生成器Rnd()(运行大约需要5秒):

Sub ZoomRNG()

Randomize
For i = 1 To 1000
    Found = False
    Do
        x = Rnd()   ' 2 random numbers between 0.0 and 1.0
        y = Rnd()
        If ((x > 0.5) And (x < 0.51)) Then
            If ((y > 0.5) And (y < 0.51)) Then
                ' Write if both x & y in a narrow range
                Cells(i, 1) = i
                Cells(i, 2) = x
                Cells(i, 3) = y
                Found = True
            End If
        End If
    Loop While (Not Found)
Next i

End Sub
Run Code Online (Sandbox Code Playgroud)

以下是运行上述代码的x与y的简单图

在此输入图像描述

它不仅具有非常随机的外观,而且比臭名昭着的RANDU算法在2D中具有更明显的超平面.基本上,我是否错误地使用了该函数,或者VBA中的Rnd()函数实际上并不是最不可用的?

为了比较,这是我在C++中获得的Mersenne Twister MT19937.

在此输入图像描述

Ana*_*a 秀 11

为了产生更好的随机生成器并使其性能更快,我修改了你的代码:

Const N = 1000           'Put this on top of your code module
Sub ZoomRNG()

Dim RandXY(1 To N, 1 To 3) As Single, i As Single, x As Single, y As Single

For i = 1 To N
    Randomize            'Put this in the loop to generate a better random numbers
    Do
        x = Rnd
        y = Rnd
        If x > 0.5 And x < 0.51 Then
            If y > 0.5 And y < 0.51 Then
                RandXY(i, 1) = i
                RandXY(i, 2) = x
                RandXY(i, 3) = y
                Exit Do
            End If
        End If
    Loop
Next
Cells(1, 9).Resize(N, 3) = RandXY
End Sub
Run Code Online (Sandbox Code Playgroud)

我在绘制结果后得到了这个

在此输入图像描述

结果看起来比代码的输出更好.稍微修改上面的代码到这样的东西

Const N = 1000
Sub ZoomRNG()

Dim RandXY(1 To N, 1 To 3) As Single, i As Single, x As Single, y As Single

For i = 1 To N
    Randomize
    Do
        x = Rnd
        If x > 0.5 And x < 0.51 Then
            y = Rnd
            If y > 0.5 And y < 0.51 Then
                RandXY(i, 1) = i
                RandXY(i, 2) = x
                RandXY(i, 3) = y
                Exit Do
            End If
        End If
    Loop
Next
Cells(1, 9).Resize(N, 3) = RandXY
End Sub
Run Code Online (Sandbox Code Playgroud)

产生比前一个更好的结果

在此输入图像描述

当然,使用C++的Mersenne Twister MT19937仍然更好,但最后的结果非常适合进行蒙特卡罗模拟.FWIW,您可能有兴趣阅读本文:关于Microsoft Excel 2010中统计程序的准确性.