如何将自定义VBA函数应用于矩阵?代码优化及循环方式咨询
改进后的VBA代码与问题解答
咱们先梳理原代码里的几个关键问题:
h和h1未声明类型与维度,VBA会默认它们为Variant类型,容易引发意外错误- 矩阵乘法
w(2×3)×i(3×1)得到的是2×1的矩阵,但原代码循环写了j=0 To 2,直接超出了矩阵范围,必然报错 h1未提前初始化就直接赋值,这也是VBA中常见的报错诱因
下面是修正并优化后的完整代码:
' 你的sigmoid函数逻辑正确,保留不动 Function sigmoid(X As Double) As Double sigmoid = 1 / (1 + Exp(-X)) End Function Sub arraymult() Dim i(0 To 2, 0 To 0) As Double Dim w(0 To 1, 0 To 2) As Double ' 明确声明h和h1的维度:MMult返回2×1矩阵,对应匹配声明 Dim h(0 To 1, 0 To 0) As Double Dim h1(0 To 1, 0 To 0) As Double Dim j As Integer ' 别忘了显式声明循环变量 ' 初始化输入矩阵i i(0, 0) = 1 i(1, 0) = 2 i(2, 0) = 6 ' 初始化权重矩阵w w(0, 0) = 2 w(0, 1) = 1 w(0, 2) = 1 w(1, 0) = 1 w(1, 1) = 1 w(1, 2) = 1 ' 执行矩阵乘法并赋值给h h = Application.WorksheetFunction.MMult(w, i) ' 遍历h的每一行,应用sigmoid生成h1 For j = LBound(h, 1) To UBound(h, 1) h1(j, 0) = sigmoid(h(j, 0)) Next j ' 可选:把结果输出到工作表方便查看(这里输出到A1、B1单元格) Range("A1:B1").Value = Application.WorksheetFunction.Transpose(h1) End Sub
关于For Each循环是否更合适的疑问
在这个场景下,普通的For循环反而比For Each更实用,原因如下:
- VBA的二维数组用For Each遍历是按列优先的顺序进行的,虽然你的矩阵是2×1的列矩阵,遍历顺序没问题,但如果是更复杂的多维矩阵,For Each很难精准定位元素的行/列位置,而带索引的For循环可以直接通过
j指定行,逻辑更清晰 - 咱们需要把h的每个元素对应放到h1的相同位置,用索引循环的代码可读性更高,不需要额外的计数器来跟踪位置
如果硬要用For Each的话也能实现,但会多一个计数器,反而增加复杂度,比如:
Dim elem As Variant Dim rowIdx As Integer rowIdx = 0 For Each elem In h h1(rowIdx, 0) = sigmoid(elem) rowIdx = rowIdx + 1 Next elem
显然这个写法不如直接用索引循环简洁。
内容的提问来源于stack exchange,提问作者Colin Namnoum
相关产品推荐
相关产品推荐

