问题描述
众所周知,Excel中的Rnd函数较弱,而Excel中的RAND函数则基于Mersenne算法且功能更强大。我一直在尝试找到一种快速而强大的替代Rnd的方法,并研究了各种选择,包括使用Mersenne,但这需要大量的代码。
解决方法
另一种选择是从VBA调用Excel RAND函数,但是一次执行一次则非常慢。但是,Excel365中的新函数RANDARRAY允许VBA一次调用Excel中的大量随机数,根据需要使用它们,并在必要时返回更多。这种方法速度快(仅比Rnd慢4倍,比Mersenne代码快4倍)且结构紧凑-代码如下。
我正在分享这个信息,希望找到解决此问题的最佳集体解决方案。
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
,
您可以使用真正的随机数-如我的项目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,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