【问题标题】:Generating fast normally distributed random numbers efficiently in Excel VBA在 Excel VBA 中有效地生成快速正态分布的随机数
【发布时间】:2020-09-02 06:42:54
【问题描述】:

我一直在寻找一种快速可靠的方法来生成正态分布的随机数。

最流行的方法似乎是使用 Excel 工作表函数 Norm_Inv 和一个随机数,但由于需要在 Excel 和 VBA 之间来回切换,因此速度很慢。

我在下面分享我的解决方案,但如果有更好的解决方案,我很想知道。

【问题讨论】:

  • Box-Muller transform 对您来说足够快吗?我不使用VB,但它就像sqrt(-2 * log(Rnd)) * cos(2*pi*Rnd)
  • 我过去曾尝试过,没关系,但是这种方法在速度上比其他所有方法都快,因为一旦你设置了数组,它就由一个随机数和一个查找组成。
  • 我想这取决于您是否可以从其范围内仅获取 1000 个可能的值。我不想担心这是否会导致我的模型出现问题,但我必须承认我不必担心,因为我一直能够有效地生成全精度(即 53 位而不是 ~10 位)变量。另一种方法可能是编写一些 C# 代码并从 VBA 调用它?
  • 如果您愿意,可以将其增加到 10000,但您需要多久使用一次该分辨率?
  • 不同的应用有不同的约束;例如即使有 10000 个元素,您也只需要生成 100 variates 就可以有约 50% 的机会看到重复(并且只有约 32 个有 1000 个数组元素)。大概这对你来说无关紧要,但这可能会破坏一些蒙特卡罗算法

标签: excel vba random normal-distribution


【解决方案1】:

此解决方案非常快速且准确无误。最初,您将区间 0-1 划分为大量切片并调用 NORM_INV 以获取每个点的正态分布值,并将这些值存储在一个数组中。之后就不需要再调用NORM_INV了,只要查找任意随机数的数组值即可。

1000 个切片似乎足以与直接使用 NORM_INV 提供 99% 以上的相关性。

Function NormalRandLookup(Optional Mean As Single = 0, Optional StdDev As Single = 1) As Single
  Static R() As Single, n As Long 
  If n = 0 Then 'set up the lookup table initially
    Dim i As Long
    n = 1000 'vary this to reduce or increase accuracy 
    ReDim R(0 To n)
    R(0) = -3.3: R(n) = 3.3 'the extreme values returned by NORM_INV for 0 and 1
    For i = 1 To n - 1 
      R(i) = Application.WorksheetFunction.Norm_Inv(i / n, 0, 1)
    Next i
  End If
  NormalRandLookup = Mean + StdDev * R(Rnd * n)
End Function

【讨论】:

    猜你喜欢
    • 2014-07-26
    • 2011-09-08
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 2018-06-22
    • 1970-01-01
    • 2012-12-11
    • 2019-06-20
    相关资源
    最近更新 更多