为了回答这个问题,我运行了以下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有时会返回相同的种子(至少不足以产生差异).
但如果这不是自相关的来源 - 那是什么?并且 - 为什么它有时表现为消极而不是积极的自相关?
仅部分答案,可自由编辑和完成。
好吧,当您过度使用 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 和随机化:
