【问题标题】:Generate "n" random numbers between a and b to reach desired average in m rows在 a 和 b 之间生成“n”个随机数以在 m 行中达到所需的平均值
【发布时间】:2018-08-26 09:28:03
【问题描述】:

假设在有 200 行的列 Z 中,是我的最佳平均值。

现在我想要一个宏,它可以在 a 和 b 之间生成 n 随机整数 (n <= 20),这样使用最佳平均值生成的数字的平均值之间的差异就在 (-0.15,+0.15) 中。

例子:

Z1:optimal average1=5.5
Z2:optimal average2=5.3

Z200:optimal average200=6.3
n=8
a=1; b=10
numbers of generated:
A1:H1)5-9-4-3-7-4-9-3
A2:H2)10-7-3-2-5-4-3-9
.
.
.
A200:H200)4-8-9-6-6-6-10-2

【问题讨论】:

  • 您能否添加您尝试过的代码并指出您遇到问题的地方。

标签: vba excel random average


【解决方案1】:

这里是一个命中或失败的方法(这通常是获得随机数的唯一可行方法,这些随机数以无偏的方式满足额外的约束):

Function RandIntVect(n As Long, a As Long, b As Long, mean As Double, tol As Double, Optional maxTries As Long = 1000) As Variant
    'Uses a hit-or-miss approach to generate a vector of n random ints in a,b inclusive whose mean is
    'within the tolerance tol of the given target mean
    'The function raises an error if maxTries misses occur without a hit

    Dim sum As Long, i As Long, j As Long
    Dim lowTarget As Double, highTarget As Double 'targets for *sums*
    Dim vect As Variant

    lowTarget = n * (mean - tol)
    highTarget = n * (mean + tol)

    For i = 1 To maxTries
        ReDim vect(1 To n)
        sum = 0
        j = 0
        Do While j < n And sum + a * (n - j) <= highTarget And sum + b * (n - j) >= lowTarget
            j = j + 1
            vect(j) = Application.WorksheetFunction.RandBetween(a, b)
            sum = sum + vect(j)
        Loop
        If j = n And lowTarget <= sum And sum <= highTarget Then
            'Debug.Print i 'uncomment this line to see how many tries required
            RandIntVect = vect
            Exit Function
        End If
    Next i
    'error if we get to here
    RandIntVect = CVErr(xlErrValue)
End Function

这可以用作worksheet array formula。目标均值在I 列中,在A2:H2 中我输入了=RandIntVect(8,1,10,I2,0.15)(使用 ctrl+shift+enter 作为数组公式),然后向下复制:

请注意,数组公式是易变的,因此每次工作表出现时都会重新计算这些数字。您可以使用 VBA 中的函数将数字直接放在范围内,而不是将函数用作工作表公式。比如:

Sub test()
    Dim i As Long
    For i = 1 To 3
        Range(Cells(i + 1, 1), Cells(i + 1, 8)).Value = RandIntVect(8, 1, 10, Cells(i + 1, 9).Value, 0.15)
    Next i
End Sub

【讨论】:

  • 两种均值之差不在范围内(+0.15,-0.15)
  • @alirezataghizadeh 当作为数组公式输入时,公式可以正常工作。这可能会令人困惑,因为 Excel 允许您将公式作为非数组公式输入,而这会以意想不到的方式工作。
【解决方案2】:

enter image description here

两种均值之差不在范围(0.15+,0.15-)内

【讨论】:

  • 从逻辑上讲,这更像是评论而不是答案,但是由于您不能在评论中发布图片,因此我理解其动机。也许你应该稍后删除它。无论如何-您的屏幕截图表明您没有在array formula 中使用该功能。请注意,在我的屏幕截图中,{=RandIntVect(8,1,10,I2,0.15)} 周围有大括号,但您的屏幕截图中缺少 {,}。
  • 另外:请注意,高于 8 的目标均值与预期样本均值 5.5 的标准差超过 2.5 个标准差。对于这些值,maxTries = 1000 未命中有时会发生(大约 5% 的时间)。如果这是您的预期用例,您应该考虑增加maxTries,无论是在函数定义本身还是在您调用它时,例如{=RandIntVect(8,1,10,I2,0.15,10000)}.
  • 非常感谢但我还是不明白我做了所有的步骤但仍然不知道我的问题在哪里
  • 您需要在A2:H2 中输入一个 数组公式,而不是每个单元格的单独公式。 1) 选择整个范围A2:H2。 2) 键入=RandIntVect(8,1,10,I2,0.15,10000)(或根据您的区域设置键入的任何内容)。不要输入{,}——Excel 会自动插入这些。 3) 使用Ctrl + Shift + Enter 将公式作为数组公式输入。无论如何——如果你只使用 VBA 来填充单元格呢?您不需要将RandIntVect 用作工作表函数——从 VBA 调用它。
猜你喜欢
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 2016-03-24
  • 1970-01-01
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 2018-07-18
相关资源
最近更新 更多