VBA随机数以规则的间隔产生重复序列

问题描述 投票:5回答:1

该代码应该在VBA中生成10,000个随机数的序列。出于某种原因,我只能生成一个长度为5842的独特序列,然后重复。但是,这是最奇怪的部分,每次运行代码时,序列都会在不同的地方开始。例如,在一次运行中,元素2660之后的元素与元素8502之后的元素相同(8502-2660 = 5842)。下一次运行,我得到一个重复以下元素3704和9546(9546-3704 = 5842)的序列。等等。

Function NormRand() As Double
' NormRand returns a randomly distributed drawing from a
' standard normal distribution i.e. one with:
' Average = 0 and Standard Deviation = 1.0
Dim fac As Double, rsq As Double, v1 As Double, v2 As Double
Static flag As Boolean, gset As Double

' Each pass through the calculation of the routine produces
'  two normally-distributed deviates, so we only need to do
'  the calculations every other call. So we set the flag
'  variable (to true) if gset contains a spare NormRand value.
If flag Then
    NormRand = gset
    ' Force calculation next time.
    flag = False
Else
    ' Don't have anything saved so need to find a pair of values
    ' First generate a co-ordinate pair within the unit circle:
    Do
        v1 = 2 * Rnd - 1#
        v2 = 2 * Rnd - 1#
        rsq = v1 * v1 + v2 * v2
    Loop Until rsq <= 1#

    ' Do the Math:
    fac = Sqr(-2# * Log(rsq) / rsq)

    ' Return one of the values and save the other (gset) for next time:
    NormRand = v2 * fac
    gset = v1 * fac
    flag = True
End If

End Function
vba ms-access random
1个回答
2
投票

出于某种原因,我只能生成一个长度为5842的独特序列,然后重复。但是,这是最奇怪的部分,每次运行代码时,序列都会在不同的地方开始

这是设计和众所周知的 - 这就是为什么数字生成被标记为伪随机而不是随机的。

顺便说一句,我注意到你正在乘以这两个值。这可能不是一个好主意 - 如here所述。

在你的函数中,你可以尝试用Rnd替换RndDbl

Public Function RndDbl(Optional ByRef Number As Single) As Double

    ' Exponent to shift the significant digits of a single to
    ' the least significant digits of a double.
    Const Exponent  As Long = 7

    Dim Value       As Double

    ' Generate two values like:
    '   0.1851513
    '   0.000000072890967130661
    ' and add these.
    Value = CDbl(Rnd(Number)) + CDbl(Rnd(Number) * 10 ^ -Exponent)

    RndDbl = Value

End Function

然后通过调用Timer修改代码以包含动态种子:

Do
    v1 = 2 * RndDbl(-Timer) - 1#
    v2 = 2 * RndDbl(-Timer) - 1#
    rsq = v1 + v2
Loop Until rsq <= 1#

生成的值仍然不是真随机的,但不应采用重复序列的形式。

© www.soinside.com 2019 - 2024. All rights reserved.