动态数组的概率随机选择
Probabilistic Random Selection from Dynamic Array
我是 VBA 的新手。我有 2 个列表,一个价格列表和一个分配给价格的概率列表。我需要根据概率组生成一个包含 300 个数字的列表。但是,我似乎无法让它工作。我从另一个 post:
上撕下了代码
Function RandItem(items As Variant, probs As Variant) As Variant
Dim i As Long, sum As Double
Dim spin As Double
spin = Rnd()
For i = LBound(probs) To UBound(probs)
sum = sum + probs(i)
If spin <= sum Then
RandItem = items(i)
Exit Function
End If
Next i
'if you get here:
RandItem = items(UBound(probs))
End Function
还有
Sub test()
Randomize
Dim i As Long, v As Variant
ReDim v(1 To 50)
For i = 1 To 50
v(i) = RandItem(Array(1, 2, 3, 4, 5), Array(0.26, 0.18, 0.26, 0.2, 0.1))
Next i
Debug.Print Join(v)
End Sub
适应我的代码。然而,问题是价格范围会扩大,并且概率会随着时间的推移而变化(由于历史权重)。所以我尝试切换:
RandItem(Array(1, 2, 3, 4, 5), Array(0.26, 0.18, 0.26, 0.2, 0.1))
到
Dim i As Long, v As Variant
Dim LastRow As Long
Dim arrayPrice As Variant
Dim arrayProPrice As Variant
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
arrayPrice = Range("A2:A" & LastRow).Value2
arrayProPrice = Range("B2:B" & LastRow).Value2
ReDim v(1 To 300)
For i = 1 To 300
v(i) = RandItem(arrayPrice, arrayProPrice)
Next i
Debug.Print Join(v)
End Sub
它返回:
运行-时间错误'9':
下标超出范围。有人对如何解决这个问题有任何建议,这样我就可以使用数组变量而不是列出所有价格范围吗?
学分:
您的动态解决方案不起作用,因为 arrayPrice
和 arrayProPrice
不是一维数组,正如 RandItem
所期望的那样,而是二维的。这是因为 Excel 范围通常可以有多行 和 多列,因此 .Value2
和 .Value
方法 return矩阵.
例如,如果在您的 Excel sheet 中有 A2=1、A3=2 和 A4=3,那么 arrayPrice
将是 Array(Array(1), Array(2), Array(3))
。
在调用 RandItem
之前,您首先必须将该矩阵展平为一维数组。 arrayProPrice
.
也是如此
您可以使用 Excel 函数来实现:
arrayPrice = Application.Transpose(Range("A2:A" & LastRow))
arrayProPrice = Application.Transpose(Range("B2:B" & LastRow))
我是 VBA 的新手。我有 2 个列表,一个价格列表和一个分配给价格的概率列表。我需要根据概率组生成一个包含 300 个数字的列表。但是,我似乎无法让它工作。我从另一个 post:
上撕下了代码Function RandItem(items As Variant, probs As Variant) As Variant
Dim i As Long, sum As Double
Dim spin As Double
spin = Rnd()
For i = LBound(probs) To UBound(probs)
sum = sum + probs(i)
If spin <= sum Then
RandItem = items(i)
Exit Function
End If
Next i
'if you get here:
RandItem = items(UBound(probs))
End Function
还有
Sub test()
Randomize
Dim i As Long, v As Variant
ReDim v(1 To 50)
For i = 1 To 50
v(i) = RandItem(Array(1, 2, 3, 4, 5), Array(0.26, 0.18, 0.26, 0.2, 0.1))
Next i
Debug.Print Join(v)
End Sub
适应我的代码。然而,问题是价格范围会扩大,并且概率会随着时间的推移而变化(由于历史权重)。所以我尝试切换:
RandItem(Array(1, 2, 3, 4, 5), Array(0.26, 0.18, 0.26, 0.2, 0.1))
到
Dim i As Long, v As Variant
Dim LastRow As Long
Dim arrayPrice As Variant
Dim arrayProPrice As Variant
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
arrayPrice = Range("A2:A" & LastRow).Value2
arrayProPrice = Range("B2:B" & LastRow).Value2
ReDim v(1 To 300)
For i = 1 To 300
v(i) = RandItem(arrayPrice, arrayProPrice)
Next i
Debug.Print Join(v)
End Sub
它返回: 运行-时间错误'9': 下标超出范围。有人对如何解决这个问题有任何建议,这样我就可以使用数组变量而不是列出所有价格范围吗?
学分:
您的动态解决方案不起作用,因为 arrayPrice
和 arrayProPrice
不是一维数组,正如 RandItem
所期望的那样,而是二维的。这是因为 Excel 范围通常可以有多行 和 多列,因此 .Value2
和 .Value
方法 return矩阵.
例如,如果在您的 Excel sheet 中有 A2=1、A3=2 和 A4=3,那么 arrayPrice
将是 Array(Array(1), Array(2), Array(3))
。
在调用 RandItem
之前,您首先必须将该矩阵展平为一维数组。 arrayProPrice
.
您可以使用 Excel 函数来实现:
arrayPrice = Application.Transpose(Range("A2:A" & LastRow))
arrayProPrice = Application.Transpose(Range("B2:B" & LastRow))