【问题标题】:Why is this code not giving any duplicates?为什么这段代码没有给出任何重复项?
【发布时间】:2019-09-14 19:39:53
【问题描述】:

我正在寻找一个彩票号码生成器,我发现了这个:

Sub LotteyCode()
Dim Rng As Range
Dim WorkRng As Range
Dim xNumbers(49) As Integer
On Error Resume Next
For xy = 1 To 10000
Set WorkRng = Range("A" & xy)
For xIndex = 1 To 49
xNumbers(xIndex) = xIndex
Next
For xIndex = 1 To 6
xNum = 1 + Application.Round(Rnd * (49 - xIndex), 0)
WorkRng.Offset(0, xIndex - 1).Value = xNumbers(xNum)
xNumbers(xNum) = xNumbers(50 - xIndex)
Next
Next xy
End Sub

我通读了代码,我一生都无法理解这是如何不生成重复数字的(代码没有解释为什么要这样写)...

我运行了 10000 次迭代(如“xy = 1 To 10000”所示)以确保它确实给出了唯一的数字。

如果有人能对此有所了解,我将非常感激!

【问题讨论】:

标签: vba random


【解决方案1】:

一开始我其实也有点迷茫,但是在我看完之后,我注意到它的工作原理是下面的第一行和第三行:

xNum = 1 + Application.Round(Rnd * (49 - xIndex), 0)
WorkRng.Offset(0, xIndex - 1).Value = xNumbers(xNum)
xNumbers(xNum) = xNumbers(50 - xIndex)

第一行从数组中选择一个随机索引,但在每次迭代中,从数组的末尾排除一个额外的索引。

第二行“挑选”(在乐透意义上)数组中该索引处的数字。

第三行将所选索引处的值替换为从该迭代中排除的数字,确保不能再次选择在该迭代中选择的数字。

【讨论】:

  • 这是Fisher-Yates-Knuth shuffle。en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
  • 我还有 2 个额外的问题...... 1. 你说:“从数组中选择一个随机索引,但在每次迭代中,从数组末尾排除一个额外的索引。” - 我在代码中遗漏了什么吗?它看起来就像一个复杂的随机数选择器...... 2. 你说:“用从该迭代中排除的数字替换所选索引处的值,确保不能再次选择在该迭代中选择的数字。” - 替换所选索引的值如何使其无法再次被选中?谢谢!
  • 1.它本质上是一个复杂的随机数选择器,但复杂之处在于确保它从列表中选择一个有效的数字。 2. 乐透“选中”的数字不是索引,而是该索引处的值。通过在选择后替换每个数字,即使再次选择了 index,结果也会选择不同的 value。在@SeverinPappadeux 提供的链接中查看modern method 的解释。它有一个例子,比我开始写的更清楚。
猜你喜欢
  • 2022-06-13
  • 2021-02-24
  • 2020-10-11
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多