我正在尝试通过以下算法通过 vba 生成一堆随机排列:
Function RandNumber(Bottom As Integer, Top As Integer, _
Amount As Integer) As Integer()
Dim iArr As Variant
Dim i As Integer
Dim r As Integer
Dim temp As Integer
Dim bridge() As Integer
'Application.Volatile
ReDim iArr(Bottom To Top)
For i = Bottom To Top
iArr(i) = i
Next i
Randomize
For i = Top To Bottom + 1 Step -1
r = Int(Rnd() * (i - Bottom + 1)) + Bottom
temp = iArr(r)
iArr(r) = iArr(i)
iArr(i) = temp
Next i
ReDim Preserve bridge(1 To Amount)
For i = Bottom To Bottom + Amount - 1
bridge(i - Bottom + 1) = iArr(i)
Next i
RandNumber = bridge
End Function
本质上是RandNumber
它根据用户提供的底部和顶部值随机给出一个排列。示例RandNumber(1,2,1)
将是1
或2
随机的。
现在我正在通过以下例程测试此功能
Sub RandNos()
Dim z() As Variant
ReDim Preserve z(1 To 2560)
For i = 1 To 2560
z(i) = RandNumber(1, 2, 1)
Next i
For i = 1 To 2560
ThisWorkbook.Sheets("Sheet2").Range("A1").Offset(i - 1, 0) = z(i)
Next i
End Sub
令我大吃一惊的是,“随机”数字在 256 次运行后正好重复!(好的,i
上面的值 2560 并不完全是巧合。我怀疑在 256 行周围有一些模式,因此取i
为 2560)
此外,当我用稍微修改的子程序测试上述函数时:
Sub RandNos2()
For i = 1 To 2560
ActiveSheet.Range("A1").Offset((i - 1) Mod 256 + 1, Int((i - 1) / 256)) = RandNumber(1, 2, 1)
Next i
End Sub
模式消失了。(至少在 256 个值之后重复的模式消失了。不确定是否会出现另一种模式)。
现在根据我的知识,Randomize
应该通过生成适当Randomize
的种子来控制随机性,并在 vba 中从timer
. 所以我的假设是,在第一RandNos()
个子程序中,更新发生得如此之快,以至于种子的更新速度不够快。当我使用第二个子例程进行测试时,模式消失的事实,因为在第二个例程中,excel 在工作表中编写代码需要更长的时间,因此给代码一些机会来更新timer
随机数的种子 -支持我的假设。
所以我的问题是
- 我的假设是否正确。
- 我是否仍希望在 Excel VBA 中生成“随机”模式。
- 我是不是用错了
Randomize
这里
提前感谢您对此问题的建议。
编辑:评论中的建议之一是我们应该Randomize
只打电话一次。我试过这样做,它似乎工作。但是,我仍然想知道使用Randomize
上述方法出了什么问题。