プログラムリスト
VBAのプログラムリストは以下のようになります。
'N=行列式の次数
'A(N,N)=固有値を求める行列
'B(N,N)=相似変換行列
'BINV(N,N)=相似変換の逆行列
'C(N,N)=相似変換後の行列
Dim A(51, 51), B(51, 51), C(51, 51), BINV(51, 51), RE(51), IM(51), N, Pn
Dim AA(51), BB(51), CC(51)
Dim M, PP, QQ, CT, ZZ, DP, DQ, EPS, ERR, EN
Sub Main()
Sheets("Sheet2").Cells.Clear
Sheets("Sheet3").Select
Sheets("Sheet3").Cells.Clear
N = Sheets("Sheet1").Cells(4, 3).Value
EN = 200 '演算回数制限値
EPS = 0.00000001 '誤差判定値
For i = 1 To N
For j = 1 To N
A(i, j) = Sheets("Sheet1").Cells(8 + i, 1 + j).Value
Next j
RE(i) = 0: IM(i) = 0
Next i
'ダニレフスキー法
DANILEVSKY
'ベアストウ法
BAIRSTOW
OUTPUT_B
End Sub
'ダニレフスキー法
Sub DANILEVSKY()
L = N - 1
Do
For i = 1 To N
For j = 1 To N
B(i, j) = 0: C(i, j) = 0: BINV(i, j) = 0
Next j
B(i, i) = 1: BINV(i, i) = 1
Next i
For j = 1 To N
B(L, j) = -A(L + 1, j) / A(L + 1, L)
Next j
B(L, L) = 1 / A(L + 1, L)
'反転処理
For j = 1 To N
BINV(L, j) = A(L + 1, j)
Next j
'AB積
For i = 1 To N
For j = 1 To N
PP = 0
For k = 1 To N
PP = PP + A(i, k) * B(k, j)
Next k
C(i, j) = PP
Next j
Next i
'BINV*C積
For i = 1 To N
For j = 1 To N
PP = 0
For k = 1 To N
PP = PP + BINV(i, k) * C(k, j)
Next k
A(i, j) = PP
Next j
Next i
Pn = N - L
OUTPUT_A
L = L - 1
Loop While L > 0
End Sub
'ベアストウ法
Sub BAIRSTOW()
For j = 1 To N
AA(j) = -A(1, j)
Next j
AA(0) = 1
M = N
Do Until M = 0
If M = 1 Then RE(M) = -AA(1): Exit Do
PP = 1: QQ = 1
CT = 0
A0 = AA(0)
For i = 0 To M
AA(i) = AA(i) / A0
Next i
If M = 2 Then
PP = AA(1): QQ = AA(2)
Else
REPEAT
End If
QUADRATIC
M = M - 2
For i = 1 To M
AA(i) = BB(i)
Next i
Loop
End Sub
Sub REPEAT()
Do
CT = CT + 1
BB(0) = 1
BB(1) = AA(1) - PP
BB(2) = AA(2) - PP * BB(1) - QQ
For j = 3 To M
BB(j) = AA(j) - PP * BB(j - 1) - QQ * BB(j - 2)
Next j
CC(0) = 1
CC(1) = BB(1) - PP
CC(2) = BB(2) - PP * CC(1) - QQ
For j = 3 To M - 1
CC(j) = BB(j) - PP * CC(j - 1) - QQ * CC(j - 2)
Next j
ZZ = CC(M - 2) ^ 2 - CC(M - 3) * (CC(M - 1) - BB(M - 1))
DP = (CC(M - 2) * BB(M - 1) - CC(M - 3) * BB(M)) / ZZ
DQ = (CC(M - 2) * BB(M) - BB(M - 1) * (CC(M - 1) - BB(M - 1) - BB(M - 1))) / ZZ
PP = PP + DP: QQ = QQ + DQ
If CT > EN Then ERR = 1: Exit Do
Loop Until Abs(DP) < EPS And Abs(DQ) < EPS
End Sub
Sub QUADRATIC()
DD = PP ^ 2 - 4 * QQ
B1 = -0.5 * PP
B2 = Sqr(Abs(DD)) * 0.5
RE(M) = B1: RE(M - 1) = B1
If DD <= 0 Then
IM(M) = B2: IM(M - 1) = -B2
Else
If PP > 0 Then B2 = -B2
RE(M) = B1 + B2
RE(M - 1) = QQ / RE(M)
End If
End Sub
Sub OUTPUT_A()
Sheets("Sheet2").Cells(1 + 10 * (Pn - 1), 1).Formula = "ダニレフスキー法計算回数=" & Pn
For j = 1 To N
Sheets("Sheet2").Cells(1 + 10 * (Pn - 1) + 1, j + 1).Formula = "j=" & j
Next j
For i = 1 To N
Sheets("Sheet2").Cells(1 + 10 * (Pn - 1) + i + 1, 1).Formula = "i=" & i
For j = 1 To N
Sheets("Sheet2").Cells(1 + 10 * (Pn - 1) + i + 1, j + 1).Value = A(i, j)
Next j
Next i
End Sub
Sub OUTPUT_B()
Sheets("Sheet3").Cells(1, 1).Formula = "ベアストウ法計算回数=" & CT
If ERR = 1 Then
Sheets("Sheet3").Cells(13, 6).Formula = "エラー"
Else
Sheets("Sheet3").Cells(2, 2).Formula = "実数部"
Sheets("Sheet3").Cells(2, 3).Formula = "虚数部"
For i = 1 To N
Sheets("Sheet3").Cells(2 + i, 1).Formula = "λ" & i
Sheets("Sheet3").Cells(2 + i, 2).Value = RE(i)
Sheets("Sheet3").Cells(2 + i, 3).Value = IM(i)
Next i
End If
End Sub