我在名为NLRegress的子程序中收到错误。我认为数组类型与Sub NLRegress中第一次调用中的数组类型不同。 Z矩阵是以下数组[1,0.2,0.04:1,0.5,0.25:1,0.8,0.64:1,1.2,1.44:1,1.7,2.89:1,2,4]
这是我的代码:
Option Explicit
Option Base 1
Sub Main()
Dim x() As Double, y() As Double, n As Integer, p As Integer, _
a() As Double, syx As Double, r2 As Double, m As Integer, _
yf() As Double, Z() As Double
Dim i As Integer, k As Integer
For k = 1 To 100
If Worksheets("Sheet1").Range("A2").Cells(k, 1).Value <> "" Then
n = n + 1 'counts the number of data points
Else
Exit For
End If
Next k
For k = 1 To 100
If Worksheets("Sheet1").Range("B2").Cells(k, 1).Value <> "" Then
p = p + 1 'counts the number of data points
Else
Exit For
End If
Next k
If p = n Then
p = n
ReDim yf(n)
Else: MsgBox ("Unequal number of x and y values")
End If
ReDim x(n)
ReDim y(n)
For i = 1 To n 'Read data for matrix x
x(i) = _
Worksheets("Sheet1").Range("A2").Cells(i, 1).Value
Next
For i = 1 To n 'Read data for matrix y
y(i) = _
Worksheets("Sheet1").Range("B2").Cells(i, 1).Value
Next
m = Worksheets("Sheet1").Range("E2").Value
ReDim a(m + 1)
Call BuildZP(x, Z, n, m)
Call NLRegress(Z, y, a, n, m)
Call MultiplyMatrixByVector(Z, a, yf)
End Sub
Sub Fitted_Data(yf, a, x, n)
Dim q As Integer
For q = 1 To n
yf(q) = a(1) + a(2) * x(q) + a(3) * x(q) ^ 2
Worksheets("Sheet1").Range("C2").Cells(q, 1).Value = yf(q)
Next
End Sub
Sub NLRegress(Z, y, a, n, m)
Dim er As Double, tol As Double, ZT() As Double, ZTZ() As Double, ZTZI() As Double, ZTY() As Double
er = 0
tol = 0.0001
ReDim ZT(m + 1, n)
Call TransposeMatrix(Z, ZT)
Call MultiplyMatrices(ZT, Z, ZTZ)
Call MatrixInverse(ZTZ, ZTZI, m + 1, tol, er)
Call MultiplyMatrixByVector(ZT, y, ZTY)
Call MultiplyMatrixByVector(ZTZI, ZTY, a)
End Sub
Sub BuildZP(x, Z, n, m)
Dim i As Integer, j As Integer
ReDim Z(n, m + 1)
For i = 1 To n
For j = 1 To m + 1
Z(i, j) = x(i) ^ (j - 1)
Next j
Next i
End Sub
答案 0 :(得分:2)
这个答案可能无法解决您的问题(请参阅我的评论) - 但是让我尽可能地为您提供一些最佳实践,这些实践可能会使VBA中的编程变得更容易,并且可能会在您的下一个项目中首先防止此类错误。
尝试将以下内容纳入您的编程
For
,If
,While
,将所包含的代码块进一步缩进一层。例如。您的前几行代码应该看起来像For k = 1 To 100 If Worksheets("Sheet1").Range("A2").Cells(k, 1).Value <> "" Then n = n + 1 'counts the number of data points Else Exit For End If Next k
Option Explicit
,这很棒。但是,您还应该在过程/函数调用中正确Dim
每个变量 - 例如Sub Fitted_Data(yf as Double, ...)
x = StartRange.Resize(NumberOfRows).Cells
,您可以用更少的代码实现这一点 - 并且执行速度更快
同样的事情是找到第一个空白行 - 而不是循环,使用StartRange.End(xlDown)
- 这将返回最后一个非空白行!StartRange.Resize(NumberOfRows) = x
。Worksheets("Sheet1").Range("A2")
会导致问题,例如重命名工作表或插入行/列。更好地分配单元格A2和B2名称,例如StartVector1
然后使用Range("StartVector1")
访问它们。更加健壮 - 而且您的代码不那么混乱Call Sub(x, y)
- Sub x, y
等同于VBA transposedX = worksheetFunctions.Transpose(x)
这是前几个
的代码结构Option Explicit
Private mVec1() As Double 'Better give a better name representing the target content of variable
Private mVec2() As Double 'I use m as a prefix to indicate module wide scoped variables
Public Sub SubDoingSomething() 'Use a name that tells the reader what the sub does
LoadVectors
BuildZP Z, n, m 'use proper variable names here
NLRegress Z, y, a, n, m 'and maybe use some more module wide variables that you don't need to pass
MultiplyMatrixByVector Z, a, yf
End Sub
Private Sub LoadVectors()
Dim count1 As Long, count2 As Long
count1 = GetRowLength(Range("StartVector1"))
count2 = GetRowLength(Range("StartVector2"))
If count1 <> count2 Then
MsgBox ("Unequal number of x and y values")
End
End If
mVec1 = Range("StartVector1").Resize(count1).Cells
mVec2 = Range("StartVector2").Resize(count2).Cells
End Sub
Private Function GetRowLenght(rng As Range)
If rng.Offset(1) = "" Then
GetRowLength = 1
Else
GetRowLength = rng.End(xlDown).Row - rng.Row + 1
End If
End Function