Excel VBA:函数中转置向量和矩阵的乘积

时间:2019-07-06 02:40:14

标签: excel vba

我有一个3x3矩阵“ mat”和一个实数矢量“ vec”(3x1),我想在VBA函数中对矩阵进行乘(线性代数意义上):t(vec) mat vec产生一个我可以在方程式中使用的1x1实数。

我不想与函数中的工作表进行交互。矩阵和向量中的值可以通过函数进行硬编码或计算。应该有一种简单的转置方法,然后像在MATLAB或R中那样进行几个矩阵乘法。这是我到目前为止的位置:

Public Function QuickMaths()
Dim vec As Variant
Dim mat As Variant
mat = Array(Array(1,1+1,3), _ 
          Array(2^2,5,6), _
          Array(7,8,9))
vec = Array(2*5,11,12)
QuickMaths = Application.WorksheetFunction.MMult(Application.WorksheetFunction.MMult(Application.WorksheetFunction.Transpose(vec), mat), vec)

End Function

我在工作表中从中获得#VALUE。我希望输出为1x1矩阵,但我不知道Excel VBA是否会考虑可以将标量作为单个值输出到工作表中的标量(例如Double)。

请发送帮助。

1 个答案:

答案 0 :(得分:1)

如果您提供了预期的输出(最后您期望的特定标量),那就太好了。

根据我从您的代码和问题中收集的信息,我将假设您正在尝试执行两个步骤。第一个是:

First step

第二个是:

Second step

(自从我做任何矩阵乘法以来已经有一段时间了,所以如果您认为我被误解了,请告诉我。)

您的第一个数组(this.setState(locationValues: list2) )是数组的数组(不是二维数组),我不认为mat处理(https://support.office.com/en-us/article/mmult-function-40593ed7-a3cd-4b6b-b9a3-e4ad3c7245eb)。因此,您可能需要替换:

MMULT

具有:

mat = Array(Array(1, 1 + 1, 3), _
          Array(2 ^ 2, 5, 6), _
          Array(7, 8, 9))

也就是说,手动分配每个数组元素可能是不切实际的,因此也许可以为您做一个小函数(请参见下面的代码中的ReDim mat(0 To 2, 0 To 2) mat(0, 0) = 1 mat(0, 1) = 2 mat(0, 2) = 3 mat(1, 0) = 4 mat(1, 1) = 5 mat(1, 2) = 6 mat(2, 0) = 7 mat(2, 1) = 8 mat(2, 2) = 9 函数)。

根据我最近30分钟在线阅读的内容,矩阵乘法不是可交换的,并且还要求第一个矩阵中的列数必须与第二个矩阵中的行数相匹配。 (您可能已经知道所有这些,但无论如何都只提到它。)

基于上述内容,您的代码可能类似于:

FlattenAnArrayOfArrays

结束点:

  • Option Explicit Public Function QuickMaths() As Variant ' This function returns a value of type Variant. ' Could return a Long/Double/numeric type; scalar should be at QuickMaths(1,1) ' But MMULT can return non-numeric values, so you risk ' getting a type mismatch error if the matrix multiplication ' is not successful (for whatever reason). ' Maybe this shouldn't be this function's concern -- or maybe it should. Dim mat As Variant mat = Array(Array(1, 1 + 1, 3), _ Array(2 ^ 2, 5, 6), _ Array(7, 8, 9)) mat = FlattenAnArrayOfArrays(mat) Dim vec As Variant vec = Array(2 * 5, 11, 12) Dim resultantMatrix As Variant resultantMatrix = Application.MMult(vec, mat) ' Number of columns in "vec" must match number of rows in "mat" resultantMatrix = Application.MMult(vec, Application.Transpose(resultantMatrix)) QuickMaths = resultantMatrix End Function Private Function FlattenAnArrayOfArrays(ByRef arrayOfArrays As Variant) As Variant() ' Given an array of arrays, returns a two-dimensional array. ' This function is very basic and has no error handling implemented. Dim firstArray() As Variant firstArray = arrayOfArrays(LBound(arrayOfArrays)) ' Columns inferred from first array in "arrayOfArrays" Dim outputArray() As Variant ReDim outputArray(LBound(arrayOfArrays) To UBound(arrayOfArrays), LBound(firstArray) To UBound(firstArray)) Dim rowIndex As Long For rowIndex = LBound(outputArray, 1) To UBound(outputArray, 1) Dim columnIndex As Long For columnIndex = LBound(outputArray, 2) To UBound(outputArray, 2) outputArray(rowIndex, columnIndex) = arrayOfArrays(rowIndex)(columnIndex) Next columnIndex Next rowIndex FlattenAnArrayOfArrays = outputArray End Function 函数的返回值是1x1矩阵,但是您可以将其分配给单元格的值。
  • 类似地,如果您从工作表单元格调用QuickMaths函数,则该单元格将显示返回值(没有任何问题或不需要数组公式)。