Excel VBA 中的数组。在某些时候它用 NA 代替值
Arrays in Excel VBA. At some point it puts NA instead of the value
我正在尝试在 Excel VBA 中进行一个简单的模拟,我们掷两个骰子。得到“1”+“2”或“1”+“3”的概率是多少?
这是我的代码:
Sub ProbabilityMeyerArray()
Dim i As Long
Dim ArrayDices(1 To 100000, 1 To 2) As Variant
Dim ArrayResult(1 To 100000) As Variant
'Simulation
For i = 1 To 100000
ArrayDices(i, 1) = WorksheetFunction.RandBetween(1, 6)
ArrayDices(i, 2) = WorksheetFunction.RandBetween(1, 6)
If (ArrayDices(i, 1) = 1 And ArrayDices(i, 2) = 3) _
Or (ArrayDices(i, 1) = 1 And ArrayDices(i, 2) = 2) _
Or (ArrayDices(i, 1) = 3 And ArrayDices(i, 2) = 1) _
Or (ArrayDices(i, 1) = 2 And ArrayDices(i, 2) = 1) Then
ArrayResult(i) = 1
Else
ArrayResult(i) = 0
End If
Next i
'print the values to cells
Range("A1:B100000").Value = ArrayDices
Range("C1:C100000").Value = WorksheetFunction.Transpose(ArrayResult)
'Calculate the probability
Probability = Application.WorksheetFunction.Sum(ArrayResult) / 100000
MsgBox "The Probability is " & Probability
End Sub
问题是,当我将数组中的值打印到单元格时,C 列中有 0 和 1(应该是),但是从第 34465 行我得到 NA。这是屏幕截图:
因此,出于某种原因,它开始使用 NA 而不是 0 和 1。计算也无法正常工作,因为概率太低,我猜这是因为它只计算前 34464 个零和一, 同时除以 100 000。你能帮我理解这里出了什么问题吗?这似乎是(我对)数组的问题,因为我可以 运行 没有数组的类似模拟(通过简单地使用单元格),并且它有效。
提前致谢!
正如@RaymondWu 在评论中所说,问题在于 Transpose
函数对其可以操作的数组长度有限制。此限制介于 65k 和 66k 列之间。
确实,您的代码将 运行 达到预期的 65k 次迭代。
您可以轻松避免使用 transpose
,老实说,我一开始并没有看到使用它的理由。
不是将数组声明为 Dim ArrayResult(1 To 100000) As Variant
,默认情况下它是 1 row x 100000 columns
,您可以这样声明它:
Dim ArrayResult(1 To 100000, 1 To 1) As Variant
这将使它成为 100000 rows x 1 columns
,现在可以像这样轻松地将其写在 excel 的列中:
Range("C1:C100000").Value = ArrayResult
当然,您还需要根据需要相应地更改代码:
ArrayResult(i,1) = 1
Else
ArrayResult(i,1) = 0
其他一些提示:
- 始终在代码的最顶部使用
Option Explicit
。它使变量声明成为强制性的,有助于避免错误
- 始终使用显式引用。引用
Ranges
时,最佳做法是定义它们所属的工作表,例如ThisWorkbook.Worksheets("Sheet1").Range("C1:C100000").Value = ArrayResult
我正在尝试在 Excel VBA 中进行一个简单的模拟,我们掷两个骰子。得到“1”+“2”或“1”+“3”的概率是多少?
这是我的代码:
Sub ProbabilityMeyerArray()
Dim i As Long
Dim ArrayDices(1 To 100000, 1 To 2) As Variant
Dim ArrayResult(1 To 100000) As Variant
'Simulation
For i = 1 To 100000
ArrayDices(i, 1) = WorksheetFunction.RandBetween(1, 6)
ArrayDices(i, 2) = WorksheetFunction.RandBetween(1, 6)
If (ArrayDices(i, 1) = 1 And ArrayDices(i, 2) = 3) _
Or (ArrayDices(i, 1) = 1 And ArrayDices(i, 2) = 2) _
Or (ArrayDices(i, 1) = 3 And ArrayDices(i, 2) = 1) _
Or (ArrayDices(i, 1) = 2 And ArrayDices(i, 2) = 1) Then
ArrayResult(i) = 1
Else
ArrayResult(i) = 0
End If
Next i
'print the values to cells
Range("A1:B100000").Value = ArrayDices
Range("C1:C100000").Value = WorksheetFunction.Transpose(ArrayResult)
'Calculate the probability
Probability = Application.WorksheetFunction.Sum(ArrayResult) / 100000
MsgBox "The Probability is " & Probability
End Sub
问题是,当我将数组中的值打印到单元格时,C 列中有 0 和 1(应该是),但是从第 34465 行我得到 NA。这是屏幕截图:
因此,出于某种原因,它开始使用 NA 而不是 0 和 1。计算也无法正常工作,因为概率太低,我猜这是因为它只计算前 34464 个零和一, 同时除以 100 000。你能帮我理解这里出了什么问题吗?这似乎是(我对)数组的问题,因为我可以 运行 没有数组的类似模拟(通过简单地使用单元格),并且它有效。
提前致谢!
正如@RaymondWu 在评论中所说,问题在于 Transpose
函数对其可以操作的数组长度有限制。此限制介于 65k 和 66k 列之间。
确实,您的代码将 运行 达到预期的 65k 次迭代。
您可以轻松避免使用 transpose
,老实说,我一开始并没有看到使用它的理由。
不是将数组声明为 Dim ArrayResult(1 To 100000) As Variant
,默认情况下它是 1 row x 100000 columns
,您可以这样声明它:
Dim ArrayResult(1 To 100000, 1 To 1) As Variant
这将使它成为 100000 rows x 1 columns
,现在可以像这样轻松地将其写在 excel 的列中:
Range("C1:C100000").Value = ArrayResult
当然,您还需要根据需要相应地更改代码:
ArrayResult(i,1) = 1
Else
ArrayResult(i,1) = 0
其他一些提示:
- 始终在代码的最顶部使用
Option Explicit
。它使变量声明成为强制性的,有助于避免错误 - 始终使用显式引用。引用
Ranges
时,最佳做法是定义它们所属的工作表,例如ThisWorkbook.Worksheets("Sheet1").Range("C1:C100000").Value = ArrayResult