⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matrixmodule.bas

📁 清华大学2002年出版的《科学与工程数值计算算法VB》配套源码
💻 BAS
📖 第 1 页 / 共 5 页
字号:
        Next j
    Next i
End Sub


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  模块名:MatrixModule.bas
'  函数名:Cal2
'  功能:  内部过程,供MUav函数调用
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub Cal2(fg() As Double, cs() As Double)

    Dim r As Double, d As Double

    If ((Abs(fg(1)) + Abs(fg(2))) = 0#) Then
        cs(1) = 1#
        cs(2) = 0#
        d = 0#
    Else
        d = Sqr(fg(1) * fg(1) + fg(2) * fg(2))
        If (Abs(fg(1)) > Abs(fg(2))) Then
            d = Abs(d)
            If (fg(1) < 0#) Then d = -d
        End If

        If (Abs(fg(2)) >= Abs(fg(1))) Then
            d = Abs(d)
            If (fg(2) < 0#) Then d = -d
        End If
        cs(1) = fg(1) / d
        cs(2) = fg(2) / d
    End If

    r = 1#
    If (Abs(fg(1)) > Abs(fg(2))) Then
        r = cs(2)
    Else
        If (cs(1) <> 0#) Then
            r = 1# / cs(1)
        End If
    End If

    fg(1) = d
    fg(2) = r

End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  模块名:MatrixModule.bas
'  函数名:MInv
'  功能:  求矩阵的广义逆
'  参数:   m    - Integer型变量。系数矩阵的行数, m>=n
'           n    - Integer型变量。系数矩阵的列数,n<=m
'          dblA  - Double型二维数组,体积为m x n。存放待分解矩阵;
'                  返回时,其对角线存放矩阵的奇异值(以非递增次序排列),其余元素为0。
'          dblAP - Double型二维数组,体积为n x m。返回时存放矩阵的广义逆。
'          dblU  - Double型二维数组,体积为m x m。返回时,存放奇异值分解式中的左奇异向量U。
'          dblV  - Double型二维数组,体积为n x n。返回时,存放奇异值分解式中的右奇异向量VT。
'           ka  - Integer型变量。ka=max(m,n)+1
'          eps  - Double型变量。奇异值分解函数中的控制精度参数。
'  返回值: Boolean型。False,失败无解;True, 成功
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function MInv(m As Integer, n As Integer, dblA() As Double, dblAP() As Double, dblU() As Double, dblV() As Double, ka As Integer, eps As Double) As Boolean
    ' 局部变量
    Dim i As Integer, j As Integer, k As Integer, l As Integer

    If Not MUav(m, n, dblA, dblU, dblV, ka, eps) Then
        MInv = False
        Exit Function
    End If

    j = n
    If (m < n) Then j = m
    j = j - 1
    k = 0
    While (k <= j)
        If (dblA(k + 1, k + 1) = 0#) Then GoTo o_lable
        k = k + 1
    Wend
    
o_lable:
    k = k - 1
    For i = 0 To n - 1
        For j = 0 To m - 1
            dblAP(i + 1, j + 1) = 0#
            For l = 0 To k
                dblAP(i + 1, j + 1) = dblAP(i + 1, j + 1) + dblV(l + 1, i + 1) * dblU(j + 1, l + 1) / dblA(l + 1, l + 1)
            Next l
        Next j
    Next i

    MInv = True
    
End Function

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  模块名:MatrixModule.bas
'  函数名:MSymTri
'  功能:  用豪斯荷尔德变换约化对称矩阵为对称三对角矩阵
'  参数:   n    - Integer型变量,对称矩阵的阶数。
'          dblA  - Double型二维数组,体积为n x n。存放n阶对称矩阵。
'          dblQ  - Double型二维数组,体积为n x n。返回时存放豪斯荷尔德变换的乘积矩阵Q。
'          dblT - Double型二维数组,体积为n x n。返回时存放对称三对角矩阵T。
'          dblB - Double型一维数组,长度为n。返回时存放对称三对角矩阵T主对角线上的元素。
'          dblC - Double型一维数组,长度为n。返回时前n-1个元素存放对称三对角矩阵T次对角线上的元素。
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub MSymTri(n As Integer, dblA() As Double, dblQ() As Double, dblT() As Double, dblB() As Double, dblC() As Double)
    Dim i As Integer, j As Integer, k As Integer
    Dim h As Double, f As Double, g As Double, h2 As Double

    For i = 1 To n
        For j = 1 To n
            dblQ(i, j) = dblA(i, j)
        Next j
    Next i

    For i = n To 2 Step -1
        h = 0#
        If (i > 2) Then
            For k = 1 To i - 1
                h = h + dblQ(i, k) * dblQ(i, k)
            Next k
        End If

        If (h + 1# = 1#) Then
            dblC(i) = 0#
            If (i = 2) Then dblC(i) = dblQ(i, i - 1)
            dblB(i) = 0#
        Else
            dblC(i) = Sqr(h)
            
            If (dblQ(i, i - 1) > 0#) Then dblC(i) = -dblC(i)
            
            h = h - dblQ(i, i - 1) * dblC(i)
            dblQ(i, i - 1) = dblQ(i, i - 1) - dblC(i)
            f = 0#

            For j = 1 To i - 1
                dblQ(j, i) = dblQ(i, j) / h
                g = 0#
                For k = 1 To j
                  g = g + dblQ(j, k) * dblQ(i, k)
                Next k

                If (j + 1 <= i - 1) Then
                    For k = j + 1 To i - 1
                        g = g + dblQ(k, j) * dblQ(i, k)
                    Next k
                End If

                dblC(j) = g / h
                f = f + g * dblQ(j, i)
            Next j

            h2 = f / (h + h)
            For j = 1 To i - 1
                f = dblQ(i, j)
                g = dblC(j) - h2 * f
                dblC(j) = g
                For k = 1 To j
                    dblQ(j, k) = dblQ(j, k) - f * dblC(k) - g * dblQ(i, k)
                Next k
            Next j

            dblB(i) = h
        End If
    Next i

    For i = 1 To n - 1
        dblC(i) = dblC(i + 1)
    Next i

    dblC(n) = 0#
    dblB(1) = 0#
    For i = 1 To n
        If ((dblB(i) <> 0#) And (i - 1 >= 0)) Then
          For j = 1 To i - 1
                g = 0#
                For k = 1 To i - 1
                    g = g + dblQ(i, k) * dblQ(k, j)
                Next k
                For k = 1 To i - 1
                    dblQ(k, j) = dblQ(k, j) - g * dblQ(k, i)
                Next k
          Next j
        End If

        dblB(i) = dblQ(i, i)
        dblQ(i, i) = 1#
        If (i - 1 >= 0) Then
            For j = 1 To i - 1
                dblQ(i, j) = 0#
                dblQ(j, i) = 0#
            Next j
        End If
    Next i
    
    ' 构造对称三对角矩阵
    For i = 1 To n
        For j = 1 To n
            dblT(i, j) = 0
            k = i - j
            If k = 0 Then dblT(i, j) = dblB(j)
            If k = 1 Then dblT(i, j) = dblC(j)
            If k = -1 Then dblT(i, j) = dblC(i)
        Next j
    Next i
    
End Sub

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'  模块名:MatrixModule.bas
'  函数名:MSymTriEigenv
'  功能:  用变形QR方法计算对称三对角矩阵的全部特征值和特征向量
'  参数:   n    - Integer型变量,对称三对角矩阵的阶数。
'          dblB - Double型一维数组,长度为n,存放对称三对角矩阵T主对角线上的元素。返回时,存放全部特征值。
'          dblC - Double型一维数组,长度为n,前n-1个元素存放对称三对角矩阵T次对角线上的元素。
'          dblQ - Double型二维数组,体积为n x n。
'                 1)如果存放单位矩阵,则返回n阶对称三对角矩阵的特征向量组。
'                 2)如果存放对称矩阵A的豪斯荷尔德变换的乘积矩阵Q(可由函数MSymTri求得),则返回n阶对称矩阵A的特征向量组。
'                    其中dblQ中的第j列为与数组dblB中第j个特征值对应的特征向量。
'          eps  - Double型变量。迭代过程中的控制精度参数。
'          nMaxItNum    - Integer。为求得一个特征值所允许的最大迭代次数。
'  返回值: Boolean型。False,失败无解;True, 成功
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Function MSymTriEigenv(n As Integer, dblB() As Double, dblC() As Double, dblQ() As Double, eps As Double, nMaxItNum As Integer) As Boolean
    ' 局部变量
    Dim i As Integer, j As Integer, k As Integer, m As Integer, it As Integer
    Dim d As Double, f As Double, h As Double, g As Double, p As Double, r As Double, e As Double, s As Double

    dblC(n) = 0#
    d = 0#
    f = 0#
    
    For j = 1 To n
        it = 0
        h = eps * (Abs(dblB(j)) + Abs(dblC(j)))
        If (h > d) Then d = h
        m = j
        While ((m <= n) And (Abs(dblC(m)) > d))
            m = m + 1
        Wend

        If (m <> j) Then
            Do
                If (it = nMaxItNum) Then
                    MSymTriEigenv = False
                    Exit Function
                End If

                it = it + 1
                g = dblB(j)
                p = (dblB(j + 1) - g) / (2# * dblC(j))
                r = Sqr(p * p + 1#)

                If (p >= 0#) Then
                    dblB(j) = dblC(j) / (p + r)
                Else
                    dblB(j) = dblC(j) / (p - r)
                End If

                h = g - dblB(j)
                For i = j + 1 To n
                  dblB(i) = dblB(i) - h
                Next i

                f = f + h
                p = dblB(m)
                e = 1#
                s = 0#
                
                For i = m - 1 To j Step -1
                    g = e * dblC(i)
                    h = e * p
                    If (Abs(p) >= Abs(dblC(i))) Then
                        e = dblC(i) / p
                        r = Sqr(e * e + 1#)
                        dblC(i + 1) = s * p * r
                        s = e / r
                        e = 1# / r
                    Else
                        e = p / dblC(i)
                        r = Sqr(e * e + 1#)
                        dblC(i + 1) = s * dblC(i) * r
                        s = 1# / r
                        e = e / r
                    End If

                    p = e * dblB(i) - s * g
                    dblB(i + 1) = h + s * (e * g + s * dblB(i))
                    For k = 1 To n
                        h = dblQ(k, i + 1)
                        dblQ(k, i + 1) = s * dblQ(k, i) + e * h
                        dblQ(k, i) = e * dblQ(k, i) - s * h
                    Next k
                Next i

                dblC(j) = s * p
                dblB(j) = e * p

            Loop While (Abs(dblC(j)) > d)

        End If

        dblB(j) = dblB(j) + f

    Next j

    For i = 1 To n
        k = i
        p = dblB(i)
        If (i + 1 <= n) Then
            j = i + 1
            While ((j <= n) And (dblB(j) <= p))
                k = j
                p = dblB(j)
                j = j + 1
            Wend
        End If

        If (k <> i) Then
            dblB(k) = dblB(i)
            dblB(i) = p
            
            For j = 1 To n
                p = dblQ(j, i)
                dblQ(j, i) = dblQ(j, k)
                dblQ(j, k) = p
            Next j
        End If
    Next i

    MSymTriEigenv = True
    
End Function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -