在 Excel VBA 中找到 Rnd 的良好替代品

问题描述 投票:0回答:3

Excel 中的 Rnd 函数众所周知很弱,而 Excel 中的 RAND 函数基于 Mersenne 算法,并且更强。我一直在尝试寻找 Rnd 的快速且强大的替代方案,并研究了各种选项,包括使用 Mersenne,但这需要大量代码。

excel vba random numbers
3个回答
2
投票

另一种选择是从 VBA 调用 Excel RAND 函数,但一次调用一个时速度非常慢。然而,Excel365中的新函数RANDARRAY允许VBA一次性从Excel中调用大量随机数,根据需要使用它们,并在需要时返回更多。这种方法速度快(仅比 Rnd 慢 4 倍,比 Mersenne 代码快)且紧凑 - 代码如下。

我分享这个是希望找到解决这个问题的最佳集体解决方案。

Function RandXL() As Single
  Static Remaining As Long, R() As Variant
  If Remaining = 0 Then 'get more numbers if necessary
    R = Application.WorksheetFunction.RandArray(1000, 1)
    Remaining = 1000
  End If
  RandXL = R(Remaining, 1)
  Remaining = Remaining - 1
End Function

0
投票

我认为通过“质量随机性”,您希望顺序生成的集合中的随机数是独立的。 一些 RNG 在一次取一个数字时表现出色,但每个随机数与其后继数之间具有很强的相关性。 很容易通过 x' = (x + ir) mod 1 生成,其中 ir 是任何无理数,例如 2 的平方根。(您实际上无法在计算机内存中保存无理数,但您可以足够接近 gubbermint 工作。 )事实上,这个 RNG 是如此完美均匀,以至于对于单维积分,通常用于减少方差的蒙特卡洛方法毫无价值。 韦尔定理在这里发挥了重要作用。

数值食谱说要结合使用两种不同的方法。 两种这样的方法是 MWC 和移位 XOR。 这些都很容易实现。 如果您需要较长的时间,您可以通过使用滞后的 MWC 获得类似 2^400,000 的东西。 无论是你还是太阳,都无法持续足够长的时间来耗尽那么多人。 有关详细信息,请在线查看该书,或扫描 George Marsaglia 的论文。

重要的一点:MWC 方法可以提供零,如果您使用 1,这将使您的正态分布函数崩溃。 所以它需要捕获零。 此外,在 MWC 下,所有零并非都相等,因为除了随机数之外,种子的状态还包括进位。 这肯定不是零,否则算法将只提供零,即使在太阳熄灭后也是如此。

不管怎样,我在我的手持式计算器上对这两种方法进行了编程,并对它们进行了明显的测试,它们通过了,但 RANDU 失败了。


-1
投票

您可以使用真正的随机数 - 如我的项目VBA.Random中所示。

它包含 Rnd 的直接替换:

' Returns a true random number as a Double, like Rnd returns a Single.
' The value will be less than 1 but greater than or equal to zero.
'
' Usage: Excactly like Rnd:
'
'   TrueRandomValue = RndQrn[(Number)]
'
'   Number < 0  ->  The same number every time, using Number as the seed.
'   Number > 0  ->  The next number in the pseudo-random sequence.
'   Number = 0  ->  The most recently generated number.
'   No Number   ->  The next number in the pseudo-random sequence.
'
' 2019-12-21. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function RndQrn( _
    Optional ByVal Number As Single = 1) _
    As Double
    
    Static Value            As Double
    
    Select Case Number
        Case Is > 0 Or (Number = 0 And Value = 0)
            ' Return the next number in the random sequence.
            Value = CDbl(QrnDecimal)
        Case Is = 0
            ' Return the most recently generated number.
        Case Is < 0
            ' Not supported by QRN.
            ' Retrieve value from RndDbl.
            Value = RndDbl(Number)
    End Select
    
    ' Return a value like:
    ' 0.171394365283966
    RndQrn = Value
    
End Function

此外,还包含一个演示 (

RandomQrn.xlsm
) 可供下载。

这设置了对 Microsoft Access 16.0 对象库 的引用,其中使用了 Nz 函数。如果您不想使用此参考,可以使用此替代品:

' Replacement for the function Application.Nz() of Access.
'
' 2015-12-10. Gustav Brock, Cactus Data ApS, CPH.
'
Public Function Nz( _
    ByRef Value As Variant, _
    Optional ByRef ValueIfNull As Variant = "") _
    As Variant

    Dim ValueNz     As Variant
    
    If Not IsEmpty(Value) Then
        If IsNull(Value) Then
            ValueNz = ValueIfNull
        Else
            ValueNz = Value
        End If
    End If
        
    Nz = ValueNz
    
End Function
© www.soinside.com 2019 - 2024. All rights reserved.