VBA rand如何使用上限和下限生成随机数字?

所以也许这是多余的,也许这就像是问为什么大多数人类是用5个手指出生的,最后的简短答案总是:因为这就是它是如何的,它只是工作,但我讨厌这个答案,而且我很想知道如何在VBA中的Rnd()函数工作。

Office Excel女士的MSDN表示,RND被定义为:

Rnd[(number)] 'The optional number argument is a Single or any valid numeric expression.

它继续说

“数字的值决定了Rnd如何生成一个随机数:对于任何给定的初始种子,都会生成相同的数字序列,因为对Rnd函数的每个连续调用都使用前一个数作为序列中下一个数的种子。

其次是:

要在给定范围内产生随机整数,请使用以下公式:

Int((upperbound - lowerbound + 1) * Rnd + lowerbound)

例如:
Dim MyValue MyValue = Int((6 * Rnd) + 1) ' Generate random value between 1 and 6.

但是,这是如何工作的? 这些数字来自哪里? 为什么6 * Rnd + 1会得到1到6之间的随机数字,而6 * Rnd + 5会得到5到10之间的数字?

而且,如果VBA的创build者如此明显地知道使用哪个公式来成功地将其缩小到特定的范围,为什么不只是将RND函数带有可选的Ubound和Lbound参数? 我不可能是唯一一个看这个公式的人吗?

在一天结束时,它的作品当然罚款任何我的伪随机数的需要,也许我正在看一个礼物马在嘴里,但仍然!


编辑


我发现这个问题可能基于math本身。 如果你采取一个小的整数你使用什么函数来使该整数适合指定的范围..所以任何人都可以解释这个公式是如何工作的?

以下是一步一步的指导:

  1. Rnd给出一个0到1之间的随机小数
  2. 6 * Rnd给出一个0到6之间的随机小数
  3. Int(6 * Rnd)舍入,以便得到介于0和5之间的随机值

生成一个下限和上限之间的随机数是很常见的。 Excel有一个RANDBETWEEN函数来做到这一点:

 Value = WorksheetFunction.RandBetween(1, 6) 

编辑:现在让我们把它适合LboundUbound (假设都是整数和Lbound < Ubound

首先定义:

 n = ubound - lbound 

接下来,我们将稍微改写MSDN公式:

  Int((ubound - lbound + 1) * Rnd + lbound) == Int((ubound - lbound + 1) * Rnd) + lbound == Int(((n + 1) * Rnd) + lbound 

从#3开始,我们知道Int(((n + 1) * Rnd)给出了一个0到n之间的随机整数,所以当你将这个随机数加到下界时,你会得到一个下界和上界之间的数字。

  Int(((n + 1) * Rnd) + lbound == 0...n + lbound == lbound...ubound 

使用公式像RndBetween像make_random_old = CLng((up - down + 1) * Rnd + down)

这是非常错误的(30分钟我的生活debugging是了解它的价格!):)

你可以检查为什么,在这里使用Sub TestMe:

 Public Sub testme() Dim l_counter As Long Dim l_random As Long For l_counter = 0 To 10000 l_random = make_random_old(0, 2) If l_random = 3 Then Debug.Print l_random Next l_counter Debug.Print "END" End Sub Public Function make_random(down As Long, up As Long) As Long make_random = CLng((up - down + 1) * Rnd + down) If make_random > up Then make_random = up If make_random < down Then make_random = down End Function Public Function make_random_old(down As Long, up As Long) As Long make_random_old = CLng((up - down + 1) * Rnd + down) End Function 

作为RndBetweem中一些随机的解决方法,使用make_random – 代码中的第二个函数。 它会为你节省很多的问题。 🙂

这可能会使得它更清晰一些:Rnd返回一个0到1范围内的随机数(这是一个单数又称分数,所以你有各种0.3948,0.001,0.8等等 – 均匀分布的伪随机数字)。 函数中的参数是用于公式和algorithm中的“易用”,但可以说不适合偶然的用户。

一般来说,Rnd实际上遵循了一个事实上的标准,即如果不是所有的编程语言(即产生一个从0.0到<1.0的随机分数),随机数生成器API是如何暴露的。 所以,如果你从VBA到Python到Java到C–你会发现它在工作方式上有惊人的相似之处。

话虽如此,许多语言(例如Python)为核心Rnd函数提供了更高级别的包装,因此在基本场景中使用起来更容易。 VBA是一种非常古老的语言 – 很less被微软更新(这是一个祝福和诅咒),所以如果你需要帮助function,你必须自己做。

在这里你可以使用什么:

 Function RndBetween(lowerbound As Int, upperbound As Int) As Int RndBetween = Int((upperbound - lowerbound + 1) * Rnd + lowerbound) End Function 

在你的代码中它变得很简单:

 RndBetween(1, 6) 

一段时间后,你将有一个辅助函数的模块,这将使生活更容易,代码更可读。 在那之前… StackOverflow 🙂