如何理解RNG种子过多造成的自相关?

Joh*_*man 5 random vba

为了回答这个问题,我运行了以下VBA实验:

Sub Test()
    Dim i As Long, A As Variant
    Dim count1 As Long, count2 As Long
    ReDim A(1 To 10000)

    For i = 1 To 10000
        Randomize
        A(i) = IIf(Rnd() < 0.5, 0, 1)
    Next i

    'count how often A(i) = A(i+1)
    For i = 1 To 9999
        If A(i) = A(i + 1) Then count1 = count1 + 1
    Next i

    For i = 1 To 10000
        A(i) = IIf(Rnd() < 0.5, 0, 1)
    Next i

    'count how often A(i) = A(i+1)
    For i = 1 To 9999
        If A(i) = A(i + 1) Then count2 = count2 + 1
    Next i

   Debug.Print "First Loop: " & count1
   Debug.Print "Second Loop: " & count2 & vbCrLf

End Sub
Run Code Online (Sandbox Code Playgroud)

当我看到这样的输出:

First Loop: 5550
Second Loop: 4976
Run Code Online (Sandbox Code Playgroud)

我非常确定我知道发生了什么:VBA正在将系统时钟转换为较低分辨率(可能是微秒),因此Randomize有时会导致两次或多次通过循环产生相同的种子.在我原来的答案中,我甚至自信地断言了这一点.但后来我再运行代码并注意到输出有时是这样的:

First Loop: 4449
Second Loop: 5042
Run Code Online (Sandbox Code Playgroud)

交替仍然引起明显的自相关 - 但是处于相反(和意外)的方向.连续通过具有相同种子的循环应该产生相同的输出,因此我们应该看到连续值比机会预测的更频繁地同意,而不是机会预测的更频繁的不同意.

现在好奇,我修改了代码:

Sub Test2()
    Dim i As Long, A As Variant
    Dim count1 As Long, count2 As Long
    ReDim A(1 To 10000)

    For i = 1 To 10000
        Randomize
        A(i) = Rnd()
    Next i

    'count how often A(i) = A(i+1)
    For i = 1 To 9999
        If A(i) = A(i + 1) Then count1 = count1 + 1
    Next i

    For i = 1 To 10000
        A(i) = Rnd()
    Next i

    'count how often A(i) = A(i+1)
    For i = 1 To 9999
        If A(i) = A(i + 1) Then count2 = count2 + 1
    Next i

   Debug.Print "First Loop: " & count1
   Debug.Print "Second Loop: " & count2 & vbCrLf

End Sub
Run Code Online (Sandbox Code Playgroud)

总是提供以下输出:

First Loop: 0
Second Loop: 0
Run Code Online (Sandbox Code Playgroud)

似乎并非连续调用Randomize有时会返回相同的种子(至少不足以产生差异).

但如果这不是自相关的来源 - 那是什么?并且 - 为什么它有时表现为消极而不是积极的自相关?

Vin*_*t G 5

仅部分答案,可自由编辑和完成。


好吧,当您过度使用 Randomize 函数时,显然存在相关性。

我尝试了以下代码,使用条件格式(值 > 0.5 的黑色填充),并且出现了明显的模式(尝试注释 Randomize 以查看更“随机”的模式。(最好使用 20 pt 列和 10%飞涨)

Function Rndmap()
    Dim i As Long, j As Long
    Dim bmp(1 To 512, 1 To 512) As Long
    For i = 1 To 512
        For j = 1 To 512
            ' Rnd -1 ' uncomment this line to get a big white and black lines pattern.
            Randomize 'comment this line to have a random pattern
            bmp(i, j) = IIf(Rnd() < 0.5, 0, 1)
        Next j
    Next i
    Range(Cells(1, 1), Cells(512, 512)) = bmp
End Function
Run Code Online (Sandbox Code Playgroud)

因此,虽然 MSDN 声明“使用 Randomize 与 number 的相同值不会重复之前的序列。”,这意味着如果 Timer 返回两次相同的值,则 Rnd 应该保持相同的随机序列而不重置,仍然有一些幕后链接..

一些截图:

仅 Rnd(): 转数

使用随机化: 随机化

使用 Rnd -1 和随机化: Rnd -1