所以我创建了一个Matrix类,该类支持:
矩阵运算-
Add
,Subtract
,Multiply
,ScalarMultiply
,Augment
,Transpose
基本行运算
SwapRows
,ScaleRow
,AddScalarMultipleRow
用于从字符串中加载矩阵的解析器-
LoadMatrixString
>实用程序功能-
ToString
和Clone
高斯消除的实现-
RowReduce
解析器是基于本教程手工编写的递归下降解析器。
基本行操作具有破坏性,因为否则会降低性能。
矩阵操作具有非破坏性,因为它们使用结果并返回。这允许方法链接,例如
Set D = A.Multiply(B).Add(C).ScalarMultiply(5)
,以及直观的行为,例如C = A x B以及A和B本身在此过程中不会被修改。我很想使这些方法具有破坏性,以提高性能(为每个中间矩阵操作创建一个对象),但是我不确定A.Multiply(B)
的结果将是A
多么直观。我在这里发布了该课程的早期版本作为对问题的答案,但此后做了一些改进。那里的测试代码仍然有效。
我特别想知道是应该将解析器拆分为一个单独的类以独立使用,还是由Matrix类本身调用。我已经尝试清理代码命名约定-子/函数使用PascalCase,变量名称使用camelCase并删除匈牙利语-但是如果我错过了一些内容,请向我指出。我一直在读,除非您专门针对性能进行编码,否则从代码可维护性的角度出发,最好在类中尽可能地调用访问器,而不是总是直接修改私有成员,因为如果访问器的实现发生变化,您就不会然后必须遍历其余代码并更改其他功能中的处理方式-听起来正确吗?
这是非常完备的
Matrix
类:Option Compare Database
Option Explicit
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByVal Destination As Long, ByVal Source As Long, ByVal Length As Integer)
'----------------------------------
'This array holds the values of the Matrix
Private matrixArray() As Double
'----------------------------------
'Shared recursive descent parsing variables
Private tempMatrixString As String
Private look As String
Public Sub Class_Initialize()
End Sub
'************************************************
'* Accessors and Utility Functions *
'***********************************
Public Property Get Value(r As Long, c As Long) As Double
CheckDimensions
Value = matrixArray(r, c)
End Property
Public Property Let Value(r As Long, c As Long, val As Double)
CheckDimensions
matrixArray(r, c) = val
End Property
Public Property Get Rows() As Long
If GetDims(matrixArray) = 0 Then
Rows = 0
Else
Rows = UBound(matrixArray, 1) + 1
End If
End Property
Public Property Get Cols() As Long
If GetDims(matrixArray) = 0 Then
Cols = 0
Else
Cols = UBound(matrixArray, 2) + 1
End If
End Property
Public Sub LoadMatrixString(str As String)
tempMatrixString = str
ParseMatrix str
tempMatrixString = ""
look = ""
End Sub
Public Sub Resize(Rows As Long, Cols As Long, Optional blPreserve As Boolean = False)
Dim tempMatrix As Matrix
Dim r As Long
Dim c As Long
If blPreserve Then
CheckDimensions
Set tempMatrix = Me.Clone
ReDim matrixArray(0 To Rows - 1, 0 To Cols - 1)
For r = 0 To MinLongs(tempMatrix.Rows, Me.Rows) - 1
For c = 0 To MinLongs(tempMatrix.Cols, Me.Cols) - 1
Value(r, c) = tempMatrix.Value(r, c)
Next
Next
Else
ReDim matrixArray(0 To Rows - 1, 0 To Cols - 1)
End If
End Sub
Public Function Clone() As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c)
Next
Next
Set Clone = mresult
End Function
Public Function ToString() As String
Dim str As String
Dim r As Long
Dim c As Long
Dim tempRow() As String
Dim tempRows() As String
ReDim tempRow(0 To Me.Cols - 1)
ReDim tempRows(0 To Me.Rows - 1)
If Not GetDims(matrixArray) = 0 Then 'Need to check if array is empty
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
tempRow(c) = Me.Value(r, c)
Next
tempRows(r) = "[" & Join(tempRow, ", ") & "]"
Next
ToString = "[" & Join(tempRows, vbCrLf) & "]"
Else
ToString = ""
End If
End Function
'***********************************************************
'* Matrix Operations *
'*********************
Public Function Add(m As Matrix) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If m.Rows = Me.Rows And m.Cols = Me.Cols Then
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c) + m.Value(r, c)
Next
Next
Else
Err.Raise vbObjectError + 1, "Matrix.Add", "Could not Add matrices: the Rows and Columns must be the same. The left matrix is (" & Me.Rows & ", " & Me.Cols & ") and the right matrix is (" & m.Rows & ", " & m.Cols & ")."
End If
Set Add = mresult
End Function
Public Function Subtract(m As Matrix) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If m.Rows = Me.Rows And m.Cols = Me.Cols Then
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c) - m.Value(r, c)
Next
Next
Else
Err.Raise vbObjectError + 2, "Matrix.Subtract", "Could not Subtract matrices: the Rows and Columns must be the same. The left matrix is (" & Me.Rows & ", " & Me.Cols & ") and the right matrix is (" & m.Rows & ", " & m.Cols & ")."
End If
Set Subtract = mresult
End Function
Public Function Multiply(m As Matrix) As Matrix
Dim mresult As Matrix
Dim i As Long
Dim j As Long
Dim n As Long
CheckDimensions
If Me.Cols = m.Rows Then
Set mresult = New Matrix
mresult.Resize Me.Rows, m.Cols
For i = 0 To Me.Rows - 1
For j = 0 To m.Cols - 1
For n = 0 To Me.Cols - 1
mresult.Value(i, j) = mresult.Value(i, j) + (Me.Value(i, n) * m.Value(n, j))
Next
Next
Next
Else
Err.Raise vbObjectError + 3, "Matrix.Multiply", "Could not Subtract matrices: the Columns of the left matrix and Rows of the right must be the same. The left matrix has " & Me.Cols & " Columns and the right matrix has " & m.Rows & " Rows."
End If
Set Multiply = mresult
End Function
Public Function ScalarMultiply(scalar As Double) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c) * scalar
Next
Next
Set ScalarMultiply = mresult
End Function
Public Function Augment(m As Matrix) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If Me.Rows = m.Rows Then
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols + m.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c)
Next
Next
For r = 0 To Me.Rows - 1
For c = 0 To m.Cols - 1
mresult.Value(r, Me.Cols + c) = m.Value(r, c)
Next
Next
Else
Err.Raise vbObjectError + 4, "Matrix.Augment", "Could not Augment matrices: the matrices must have the same number of Rows. The left matrix has " & Me.Rows & " Rows and the right matrix has " & m.Rows & " Rows."
End If
Set Augment = mresult
End Function
Public Function Transpose() As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If Me.Rows = Me.Cols Then
Set mresult = New Matrix
mresult.Resize Me.Cols, Me.Rows
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
Me.Value(r, c) = mresult(c, r)
Next
Next
Else
Err.Raise vbObjectError + 5, "Matrix.Augment", "Could not Transpose matrix: the matrix must have the same number of Rows and Cols. The matrix is (" & Me.Rows & ", " & Me.Cols & ")."
End If
Set Transpose = mresult
End Function
Public Function RowReduce() As Matrix
Dim i As Long
Dim j As Long
CheckDimensions
'Row Echelon
Dim mresult As Matrix
Set mresult = Me.Clone
For i = 0 To mresult.Rows - 1
If Not mresult.Value(i, i) <> 0 Then
For j = i + 1 To mresult.Rows - 1
If mresult.Value(j, i) > 0 Then
mresult.SwapRows i, j
Exit For
End If
Next
End If
If mresult.Value(i, i) = 0 Then
Exit For
End If
mresult.ScaleRow i, 1 / mresult.Value(i, i)
For j = i + 1 To mresult.Rows - 1
mresult.AddScalarMultipleRow i, j, -mresult.Value(j, i)
Next
Next
'Backwards substitution
For i = IIf(mresult.Rows < mresult.Cols, mresult.Rows, mresult.Cols) - 1 To 1 Step -1
If mresult.Value(i, i) > 0 Then
For j = i - 1 To 0 Step -1
mresult.AddScalarMultipleRow i, j, -mresult.Value(j, i)
Next
End If
Next
Set RowReduce = mresult
End Function
'*************************************************************
'* Elementary Row Operaions *
'****************************
Public Sub SwapRows(r1 As Long, r2 As Long)
Dim temp As Double
Dim c As Long
CheckDimensions
For c = 0 To Me.Cols - 1
temp = Me.Value(r1, c)
Me.Value(r1, c) = Me.Value(r2, c)
Me.Value(r2, c) = temp
Next
End Sub
Public Sub ScaleRow(row As Long, scalar As Double)
Dim c As Long
CheckDimensions
For c = 0 To Me.Cols - 1
Me.Value(row, c) = Me.Value(row, c) * scalar
Next
End Sub
Public Sub AddScalarMultipleRow(srcrow As Long, destrow As Long, scalar As Double)
Dim c As Long
CheckDimensions
For c = 0 To Me.Cols - 1
Me.Value(destrow, c) = Me.Value(destrow, c) + (Me.Value(srcrow, c) * scalar)
Next
End Sub
'************************************************************
'* Parsing Functions *
'*********************
Private Sub ParseMatrix(strMatrix As String)
Dim arr() As Double
Dim c As Long
GetChar 1
Match "["
SkipWhite
If look = "[" Then
arr = ParseRow
Me.Resize 1, UBound(arr) + 1
'ReDim matrixArray(0 To UBound(arr), 0 To 0)
For c = 0 To Me.Cols - 1
Me.Value(0, c) = arr(c)
Next
SkipWhite
While look = ","
Match ","
SkipWhite
arr = ParseRow
Me.Resize Me.Rows + 1, Me.Cols, True
If UBound(arr) <> (Me.Cols - 1) Then
'Error jagged array
Err.Raise vbObjectError + 6, "Matrix.LoadMatrixString", "Parser Error - Jagged arrays are not supported: Row 0 has " & Me.Cols & " Cols, but Row " & Me.Rows - 1 & " has " & UBound(arr) + 1 & " Cols."
End If
For c = 0 To Me.Cols - 1
Me.Value(Me.Rows - 1, c) = arr(c)
Next
SkipWhite
Wend
Match "]"
ElseIf look = "]" Then
Match "]"
Else
MsgBox "Error"
End If
SkipWhite
If look <> "" Then
Err.Raise vbObjectError + 7, "Matrix.LoadMatrixString", "Parser Error - Unexpected Character: """ & look & """."
End If
End Sub
Private Function ParseRow() As Variant
Dim arr() As Double
Match "["
SkipWhite
ReDim arr(0 To 0)
arr(0) = ParseNumber
SkipWhite
While look = ","
Match ","
ReDim Preserve arr(0 To UBound(arr) + 1)
arr(UBound(arr)) = ParseNumber
SkipWhite
Wend
Match "]"
ParseRow = arr
End Function
Private Function ParseNumber() As Double
Dim strToken As String
If look = "-" Then
strToken = strToken & look
GetChar
End If
While IsDigit(look)
strToken = strToken & look
GetChar
Wend
If look = "." Then
strToken = strToken & look
GetChar
While IsDigit(look)
strToken = strToken & look
GetChar
Wend
End If
ParseNumber = CDbl(strToken)
End Function
'****************************************************************
Private Sub GetChar(Optional InitValue)
Static i As Long
If Not IsMissing(InitValue) Then
i = InitValue
End If
If i <= Len(tempMatrixString) Then
look = Mid(tempMatrixString, i, 1)
i = i + 1
Else
look = ""
End If
End Sub
'****************************************************************
'* Skip Functions (Parser) *
'***************************
Private Sub SkipWhite()
While IsWhite(look) Or IsEOL(look)
GetChar
Wend
End Sub
'****************************************************************
'* Match/Expect Functions (Parser) *
'***********************************
Private Sub Match(char As String)
If look <> char Then
Expected """" & char & """"
Else
GetChar
SkipWhite
End If
Exit Sub
End Sub
Private Sub Expected(str As String)
'MsgBox "Expected: " & str
Err.Raise vbObjectError + 8, "Matrix.LoadMatrixString", "Parser Error - Expected: " & str
End Sub
'****************************************************************
'* Character Class Functions (Parser) *
'**************************************
Private Function IsDigit(char As String) As Boolean
Dim charval As Integer
If char <> "" Then
charval = Asc(char)
If 48 <= charval And charval <= 57 Then
IsDigit = True
Else
IsDigit = False
End If
Else
IsDigit = False
End If
End Function
Private Function IsWhite(char As String) As Boolean
Dim charval As Integer
If char <> "" Then
charval = Asc(char)
If charval = 9 Or charval = 11 Or charval = 12 Or charval = 32 Or charval = 160 Then '160 because MS Exchange sucks
IsWhite = True
Else
IsWhite = False
End If
Else
IsWhite = False
End If
End Function
Private Function IsEOL(char As String) As Boolean
If char = Chr(13) Or char = Chr(10) Then
IsEOL = True
Else
IsEOL = False
End If
End Function
'*****************************************************************
'* Helper Functions *
'********************
Private Sub CheckDimensions()
If GetDims(matrixArray) = 0 Then
'Error, uninitialized array
Err.Raise vbObjectError + 1, "Matrix", "Array has not been initialized"
End If
End Sub
Private Function GetDims(VarSafeArray As Variant) As Integer
Dim lpSAFEARRAY As Long
Dim lppSAFEARRAY As Long
Dim arrayDims As Integer
'This check ensures that the value inside the Variant is actually an array of some type
If (VarType(VarSafeArray) And vbArray) > 0 Then
'If the Variant contains an array, the pointer to the pointer to the array is located at VarPtr(VarSafeArray) + 8...
CopyMemory VarPtr(lppSAFEARRAY), VarPtr(VarSafeArray) + 8, 4&
'...and now dereference the pointer to pointer to get the actual pointer to the array...
CopyMemory VarPtr(lpSAFEARRAY), lppSAFEARRAY, 4&
'...which will be 0 if the array hasn't been initialized
If Not lpSAFEARRAY = 0 Then
'If it HAS been initialized, we can pull the number of dimensions directly from the pointer, since it's the first member in the SAFEARRAY struct
CopyMemory VarPtr(arrayDims), lpSAFEARRAY, 2&
GetDims = arrayDims
Else
GetDims = 0 'Array not initialized
End If
Else
GetDims = 0 'It's not an array... Type mismatch maybe?
End If
End Function
Private Function MinLongs(a As Long, b As Long) As Long
If a < b Then
MinLongs = a
Else
MinLongs = b
End If
End Function
这是几个使用示例:
Option Compare Database
Public Sub TestMatrix()
Dim m1 As Matrix
Set m1 = New Matrix
m1.LoadMatrixString ("[[ 0, 1, 4, 9, 16]," & _
" [16, 15, 12, 7, 0]," & _
" [ 1, 1, 1, 1, 1]]")
Dim m2 As Matrix
Set m2 = New Matrix
m2.LoadMatrixString ("[[190]," & _
" [190]," & _
" [ 20]]")
MsgBox m1.Augment(m2).RowReduce.ToString
End Sub
Public Sub TestMatrix2()
'This is an example iteration of a matrix Petri Net as described here:
'http://www.techfak.uni-bielefeld.de/~mchen/BioPNML/Intro/MRPN.html
Dim D_Minus As Matrix
Dim D_Plus As Matrix
Dim D As Matrix
Set D_Minus = New Matrix
D_Minus.LoadMatrixString "[[0, 0, 0, 0, 1]," & _
" [1, 0, 0, 0, 0]," & _
" [0, 1, 0, 0, 0]," & _
" [0, 0, 1, 1, 0]]"
Set D_Plus = New Matrix
D_Plus.LoadMatrixString "[[1, 1, 0, 0, 0]," & _
" [0, 0, 1, 1, 0]," & _
" [0, 0, 0, 1, 0]," & _
" [0, 0, 0, 0, 1]]"
Set D = D_Plus.Subtract(D_Minus)
MsgBox D.ToString
Dim Transition_Matrix As Matrix
Dim Marking_Matrix As Matrix
Dim Next_Marking As Matrix
Set Transition_Matrix = New Matrix
Transition_Matrix.LoadMatrixString "[[0, 1, 1, 0]]"
Set Marking_Matrix = New Matrix
Marking_Matrix.LoadMatrixString "[[2, 1, 0, 0, 0]]"
Set Next_Marking = Transition_Matrix.Multiply(D).Add(Marking_Matrix)
MsgBox Next_Marking.ToString
End Sub
#1 楼
Public Sub Class_Initialize()
End Sub
避免空成员;尽管可以推断出
r
和c
是为row
和column
设计的,但为清晰起见,这些单字母参数可能应该称为row
和column
。同样,Cols
可能应该称为Columns
。这很不幸:调用属性
ValueAt
,然后可以将val
参数称为value
-由于默认情况下传递了ByRef
参数,因此我明确指出了要传递它们ByVal
-无需通过引用传递它们:Public Property Let Value(r As Long, c As Long, val As Double)
对于
LoadMatrixString
,我考虑从此更改签名:Public Property Let ValueAt(ByVal rowIndex As Long, ByVal columnIndex As Long, ByVal value As Double)
为此:
Public Sub LoadMatrixString(str As String)
对于带有
m As Matrix
参数的成员,我会选择ByVal value As Matrix
并避免使用单字母标识符。我发现在这些情况下,“值”仍然是最具描述性的名称。命名“维度”的方式存在不一致之处:您拥有
CheckDimensions
,但是您也拥有GetDims
-我会重命名后一个GetDimensions
。我喜欢该类是独立的,但是在我看来,
ToString
实现将是使用您出色的StringBuilder
类的完美借口,并且我敢打赌,您会更快地得到字符串输出;)至此:
我特别想知道是否应该拆分将解析器分解为一个单独的类,以供单独使用,或者由Matrix类本身调用。
我认为您可以简单地将解析代码移至
MatrixParser
类,并完成它! ...实际上,我将在其中复制LoadMatrixString
过程,并将其重命名为Parse
,将其命名为Function
,并使其返回Matrix
。然后可以修改LoadMatrixString
以调用此新功能。评论
\ $ \ begingroup \ $
在VBA中使用行和列作为关键字时,是否会引起任何问题?
\ $ \ endgroup \ $
– enderland
2014-10-25 15:07
\ $ \ begingroup \ $
@enderland不是关键字-它们只是Worksheet和Range类的成员-不会阻止您拥有自己的;)
\ $ \ endgroup \ $
–马修·金登(Mathieu Guindon)♦
14-10-25在16:02
#2 楼
这绝不是完整的评论,但是我确实注意到了一些事情。如果您正在争取可维护的代码,则引发错误的方式可能会花费一些工作。 Err.Raise vbObjectError + 1, "Matrix.Add", "Could not Add matrices: the Rows and Columns must be the same. The left matrix is (" & Me.Rows & ", " & Me.Cols & ") and the right matrix is (" & m.Rows & ", " & m.Cols & ")."
因此,首先,我喜欢您将
vbObjectError
正确添加到了错误编号。我不喜欢的是是否要添加一个新错误,我必须手动查看整个文件以查看是否正在重用一个文件。这是Enum
的绝佳用法。 Public Enum MatrixError
AdditionError = vbObjectError + 1
SomeOtherError
' ...
End Enum
好处有两个。
添加和使用错误号变得更加容易。
错误号会显示在客户端代码中,因此,如果出现错误,我可以检查
Err.Number
并进行适当处理。 类似的东西:
ErrHandler:
If Err.Number = AdditionError Then
' do something to handle the matrix error
Else
' throw it upstream
Err.Raise Err.Number
End If
End Sub
#3 楼
仅需考虑几件事,而不是代码,更多地是关于Matrix类的设计和使用。在我特定而又特殊的宇宙角落,我们经常需要空矩阵,即是一个一维或零维为零的矩阵。这样的想法是,在程序执行过程中以及在一个或另一个时间点建立或破坏一个矩阵,使行为零是很自然的。准许的VBA不支持空数组,我已经解决的一种讨厌(或愚蠢)的方法是填充一个额外的行或列元素。当然,这是一些额外的空间,但这毕竟是2015年。
脚踏实地,我会使用无解析器的模拟物和LoadMatrixString的伴侣,例如
Public Sub LoadMatrixVector(rows as Long, columns as Long, values() as Double)
可能与辅助功能(如
Public Function Vector(ParamArray values() As Variant) As Double()
Dim result() As Double
ReDim result(UBound(values))
Dim i As Long
Dim item As Variant
i = 0
For Each item In values
result(i) = CDbl(values(i))
i = i + 1
Next item
Vector = result
End Function
结合使用,我可以在其中写
Set mat = LoadMatrixVector(3, 3, Vector(1, 2, 3))
/>
并得到具有三行1、2和3的矩阵。LoadMatrixVector可以根据需要包装值,直到填充结果为止。
此外,我可以将这样的事情视为可以接受的折衷方案进行适当的操作(您称其为“破坏性”)。
Set D = A.ShallowCopy().Multiply(B).Add(C).ScalarMultiply(5)
还有更多。我的建议可能会违反既定的编码惯例。我尝试兼顾简洁和清晰。
首先,我更喜欢在程序的早期处理简单的案例,以减少以后的(循环度量?)复杂性。例如,我会把一致性检查提早一点,甚至可能提早退出,而不是
Public Function Add(m As Matrix) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If m.Rows = Me.Rows And m.Cols = Me.Cols Then
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c) + m.Value(r, c)
Next
Next
Else
Err.Raise vbObjectError + 1, "Matrix.Add", "Could not Add matrices: the Rows and Columns must be the same. The left matrix is (" & Me.Rows & ", " & Me.Cols & ") and the right matrix is (" & m.Rows & ", " & m.Cols & ")."
End If
Set Add = mresult
End Function
。并不是很短,但是函数的实际业务部分更简单并且缩进更少。
Public Function Add(m As Matrix) As Matrix
Dim mresult As Matrix
Dim r As Long
Dim c As Long
CheckDimensions
If m.Rows <> Me.Rows Or m.Cols <> Me.Cols Then
Err.Raise vbObjectError + 1, "Matrix.Add", "Could not Add matrices: the Rows and Columns must be the same. The left matrix is (" & Me.Rows & ", " & Me.Cols & ") and the right matrix is (" & m.Rows & ", " & m.Cols & ")."
End If
Set mresult = New Matrix
mresult.Resize Me.Rows, Me.Cols
For r = 0 To Me.Rows - 1
For c = 0 To Me.Cols - 1
mresult.Value(r, c) = Me.Value(r, c) + m.Value(r, c)
Next
Next
Set Add = mresult
End Function
接下来,返回布尔结果的函数,例如
Private Function IsEOL(char As String) As Boolean
If char = Chr(13) Or char = Chr(10) Then
IsEOL = True
Else
IsEOL = False
End If
End Function
可以这样写
Private Function IsEOL(char As String) As Boolean
IsEOL = char = Chr(13) Or char = Chr(10)
End Function
尽管VBA在分配和相等性方面都使用=的设计决策在这里很烦人。
将这两个想法结合起来,isDigit可以变得更小
没错,您在做的事情上做得最好。
需要注释时,您才能解释自己在做什么,但否则您将假设自己的语言素养水平合理。
MultiplyScalar函数是一个不做太多事的好例子。
而不是因为VBA缺乏函数重载而不是试图在Multiply函数中分离标量和矩阵情况,而是将类型检查的重担留在了VBA所属的地方。
好东西。 >
#4 楼
使用Like
可以使isDigit更快(或更短)两倍:Private Function IsDigit(char As String) As Boolean
IsDigit = char Like "[0-9]"
End Function
评论
我一定会留意的!我认为这段代码中有一个错误;我认为Value被设计为默认属性,这意味着它需要Attribute Value.VB_UserMemId = 0标签。我之所以这样说是因为Transpose之类的方法调用了Me.Value(r,c)= mresult(c,r)之类的东西,该方法目前无法正常工作,需要用Me.Value(r,c)= mresult.Value代替。 (c,r)如果未添加标签。顺便说一句,该方法实际上应该是mresult.Value(c,r)= Me.Value(r,c)我认为,并且它不需要检查匹配的尺寸(Me.Rows = Me.Cols)转置非平方矩阵
您可以用“选项比较文本”替换“选项比较数据库”,以允许代码也可以在Excel中使用。