3
私はMSのExcel VBAで高速フーリエ変換(基数2)を実装しようとしています。私が使用しているコードは、ワークシート内の範囲からデータを取り出し、計算を行い、結果を隣接する列にダンプします。私が問題を抱えているのは、1)結果のX [k]配列で何をすべきかを知っている、2)これらの結果をFFTで作成されたExcelの結果と一致させる(現在一致していない)。コードを以下に示します。あなたの助けを前にありがとう。ExcelのVBAを使用した高速フーリエ変換
Sub Enforce_DecimationInTime()
On Error GoTo ERROR_HANDLING
Dim SubName As String
SubName = "Enforce_DecimationInTime()"
Dim WS As Worksheet
Dim n As Long, v As Long, LR As Long, x As Long
Set WS = Worksheets("FFT")
LR = WS.Range("A" & Rows.Count).End(xlUp).Row
n = LR - 1
Do Until 2^x <= n And 2^(x + 1) > n 'locates largest power of 2 from size of input array
x = x + 1
Loop
n = n - (n - 2^x) 'calculates n using the largest power of 2
If n + 1 <> WS.Range("A" & Rows.Count).End(xlUp).Row Then
WS.Range("A" & 2^x + 2 & ":A" & LR).Delete xlUp 'deletes extra input data
End If
v = WorksheetFunction.Log(n, 2) 'calculates number of decimations necessary
Application.ScreenUpdating = False
For x = 1 To v
Call Called_Core.DecimationInTime(WS, n, 2^x, x) 'calls decimation in time subroutine
Next x
Application.ScreenUpdating = True
Exit Sub
ERROR_HANDLING:
MsgBox "Error encountered in " & SubName & ": exiting subroutine." _
& vbNewLine _
& vbNewLine & "Error description: " & Err.Description _
& vbNewLine & "Error number: " & Err.Number, vbCritical, Title:="Error!"
End
End Sub
上記サブルーチン「V」のカウントにするために/ Nextループを介して以下のサブルーチンを呼び出します。
Sub DecimationInTime(WS As Worksheet, n As Long, Factor As Integer, x As Long)
On Error GoTo ERROR_HANDLING
Dim SubName As String
SubName = "DecimationInTime()"
Dim f_1() As Single, f_2() As Single
Dim i As Long, m As Long, k As Long
Dim TFactor_N1 As String, TFactor_N2 As String, X_k() As String
Dim G_1() As Variant, G_2() As Variant
ReDim f_1(0 To n/Factor - 1) As Single
ReDim f_2(0 To n/Factor - 1) As Single
ReDim G_1(0 To n/1 - 1) As Variant
ReDim G_2(0 To n/1 - 1) As Variant
ReDim X_k(0 To n - 1) As String
TFactor_N1 = WorksheetFunction.Complex(0, -2 * WorksheetFunction.Pi/(n/1)) 'twiddle factor for N
TFactor_N2 = WorksheetFunction.Complex(0, -2 * WorksheetFunction.Pi/(n/2)) 'twiddle factor for N/2
For i = 0 To n/Factor - 1
f_1(i) = WS.Range("A" & 2 * i + 2).Value 'assign input data
f_2(i) = WS.Range("A" & 2 * i + 3).Value 'assign input data
Next i
WS.Cells(1, 1 + x).Value = "X[" & x & "]" 'labels X[k] column with k number
For k = 0 To n/2 - 1
For m = 0 To n/Factor - 1
G_1(m) = WorksheetFunction.ImProduct(WorksheetFunction.ImPower(TFactor_N2, k * m), WorksheetFunction.Complex(f_1(m), 0)) 'defines G_1[m]
G_2(m) = WorksheetFunction.ImProduct(WorksheetFunction.ImPower(TFactor_N2, k * m), WorksheetFunction.Complex(f_2(m), 0)) 'defines G_2[m]
Next m
X_k(k) = WorksheetFunction.ImSum(WorksheetFunction.ImSum(G_1), WorksheetFunction.ImProduct(WorksheetFunction.ImSum(G_2), WorksheetFunction.ImPower(TFactor_N1, k))) 'defines X[k] for k
If k <= n/2 Then X_k(k + n/2) = WorksheetFunction.ImSum(WorksheetFunction.ImSum(G_1), WorksheetFunction.ImProduct(WorksheetFunction.ImSum(G_2), WorksheetFunction.ImPower(TFactor_N1, k), WorksheetFunction.Complex(-1, 0))) 'defines X[k] for k + n/2
WS.Cells(k + 2, 1 + x).Value = X_k(k)
WS.Cells(k + 2 + n/2, 1 + x).Value = X_k(k + n/2)
Next k
Exit Sub
ERROR_HANDLING:
MsgBox "Error encountered in " & SubName & ": exiting subroutine." _
& vbNewLine _
& vbNewLine & "Error description: " & Err.Description _
& vbNewLine & "Error number: " & Err.Number, vbCritical, Title:="Error!"
End
End Sub
組み込みFFTはおそらくC言語で実装されているため、VBAのものよりも少なくとも1桁は速いでしょう。なぜあなたはそれを使用したくないのですか? VBAから呼び出すことは可能です。これを参照してください:http://www.cpearson.com/excel/atp.htm –
ええ、私は、VBAがこれを他の多くの言語に比べて非常にゆっくりと実行することを認識しています。ビルトインのFFTは4096の入力配列の制限を持っていますが、私はFFTを使ってより大きな配列を実行したいと思います(時間の大幅な増加にもかかわらず)。また、私はプログラムが私のために仕事をさせるのではなく、実際のアルゴリズムを学ぶことを好むでしょう。 – senuba91
私には意味をなさない - あなたはあなたがVBAで直接使用できるかどうか分からない可能性があると思っただけです。このようなアルゴリズムを自分で実装するのは間違いなく学習体験です。より現実的な観点から見ると、おそらくこれを見ることができます:https://newtonexcelbach.wordpress.com/2015/05/05/xlscipy-1-01/(あなたがそのルートに行かなくても、この記事が掲載されているブログは、Excelでハードコアの科学計算をしたいと思っている人にとっては良い読書です) –