配列の大きさ(要素数やデータ数など)が実行前には未知で、プロシージャの実行中に確定する場合があります。たとえば、データを読み込むことで必要な配列の大きさが分る場合や項目を検索してデータ数が確定する場合などです。しかし、配列の大きさが未確定のために、あらかじめ高速フーリエ変換時の地震波データ数の取り得る最大数文の配列を設定したり、検索前の母数(データ数)の配列を設定したりすると、とても大きな容量を取り過ぎてしまい弊害が起こりそうですよね。このような場合、ReDimで配列を再定義することで、それらのデータ数に応じた配列で後の処理を実行することが可能となります。
変数で配列を定義 ReDim
プロシージャ内で配列の大きさ(要素数やデータ数など)が確定した後に、配列を再定義して、後の処理を実行します。あらかじめ配列の大きさを変数としておいて、その変数で配列を定義しておけば良いというものではありません。
まず、Dimで要素数を書かずに配列を定義しておきます。配列の大きさ(要素数orデータ数)が確定した後、ReDimを用いて配列を再定義します。配列をX、要素数をnとして構文を示します。
もし、ReDimで再定義をしない場合には、つぎのようなエラーが表示されます。
なお、わたしが確認した範囲では、データ型にプロシージャ内で定義したデータ型を使用しても実行可能でした。ちなみに、使用バージョンはOffice2021です。
プロシージャ例
ここでは、下記の関連記事で示したFFTのプロシージャにReDimを使用してみます。
プロシージャの冒頭で complex型を定義して、そのcomplex型の配列に適用しています。
Dim X() As complex と最初に要素数を定義せずに配列の定義をしておきます。つづいて、データ数NDをsheetから読み込んだ後に、ReDim X(ND) As complexとして再定義します。サブルーチン fast へは X() を引数として設定し、プロシージャ側では X() As complex で受けます。
これでプロシージャを実行すると、高速フーリエ変換が間違いなく実行されました。出力結果は省略します。
Option Explicit Dim ND As Long, N As Long, I As Long, J As Long, K As Long Dim M As Long, Kmax As Long, Istep As Long, IND As Long Dim dt As Double, pi As Double '=== 複素数と複素行列の型 === Type complex re As Double '実部 im As Double '虚部 End Type '---------- Function 等の定義(省略) ---------------------------- Sub フーリエ変換() Dim X() As complex '⇐あらかじめX()として定義 pi = 3.14159265359 ND = Range("B2").Value dt = Range("B3").Value ReDim X(ND) As complex '⇐データ数NDを読み込んだ後に再定義 For I = 1 To 14 Kmax = 2 ^ I If ND <= Kmax Then N = Kmax Exit For End If Next I For I = 1 To ND X(I) = cn(Cells(I + 1, 5), 0#) Next I If N > ND Then For I = ND + 1 To N X(I) = cn(0#, 0#) Next I End If Call fast(-1, X()) '⇐サブルーチンFFTを実行 X()を引数で '---------------------- (以下省略) ---------------------------- End Sub '=== 高速フーリエ変換 Ind=-1:FFT,Ind=1:IFFT === Sub fast(IND, X() As complex) Dim Temp As complex Dim Theta As complex '---------------------- (以下省略) ---------------------------- End Sub
容量が多く必要な計算では、ReDimで要素数(配列の大きさ)が確定した後に配列の大きさを再定義して、効率的に計算を実行することが望ましいですね。
以上、参考になれば幸いです。
コメント