ちょっとCSVで書きだす必要があったので、VBAを触ってました。


ほぼ趣味でVBAで再帰処理をしてみたのですが、やっぱりコードがすっきりして気持ちいいですね!

ですが、気になるのは計算時間。


・・・ということで調べてみました。




再帰処理と言えばn進数変換ってことで、2進数だとつまらないので16進数にしてみました。


16進数を扱うときは、10~15をA~Fにしないといけないので、この変換関数を先に準備します。


まず、ConstでBaseに16を設定し、変換用にNumChar = "0123456789ABCDEF"という文字列を用意しました。


Const Base = 16
Const NumChar = "0123456789ABCDEF"


次に一文字変換。

' 10進数を16進数文字に変換
Function Get16Char(ByVal num As Integer) As String
Get16Char = Mid(NumChar, num + 1, 1)
End Function

' 16進数文字を15以下の数字に変換
Function Get10Num(ByVal char16 As String) As Integer
Get10Num = InStr(NumChar, char16) - 1
End Function


さて、いよいよ再帰処理ですが、

' 再帰処理で10進数を16進数に変換
Function Convert10to16Recursive(ByVal num10 As Long) As String
If (num10 < Base) Then
Convert10to16Recursive = Get16Char(num10)
Exit Function
Else
Convert10to16Recursive = Convert10to16Recursive(num10 \ Base) & Get16Char(num10 Mod Base)
End If
End Function

' 再帰処理で16進数を10進数に変換
Function Convert16to10Recursive(ByVal num16 As String) As Long
If Len(num16) = 1 Then
Convert16to10Recursive = Get10Num(num16)
Exit Function
Else
Convert16to10Recursive = Get10Num(Right(num16, 1)) + Convert16to10Recursive(Mid(num16, 1, Len(num16) - 1)) * Base
End If
End Function


ちなみに、再帰処理を使わないとこんな感じ。

' 通常処理で10進数を16進数に変換
Function Convert10to16Normal(ByVal num10 As Long) As String
Do
Convert10to16Normal = Get16Char(num10 Mod Base) & Convert10to16Normal num10 = num10 \ Base
Loop Until (num10 = 0)
End Function

' 通常処理で16進数を10進数に変換
Function Convert16to10Normal(ByVal num16 As String) As Long
Dim i As Integer

For i = 1 To Len(num16)
Convert16to10Normal = Convert16to10Normal * Base + Get10Num(Mid(num16, i, 1))
Next
End Function


ま、これだけっちゃこれだけなんですが、なーんとなく

計算時間

が気になりませんか?・・・ということで調べました。


単純に10進数の123456を16進数にする処理を100000回計算してみると、

  • 再帰処理: 0.4375秒
  • 通常処理: 0.3672秒
  • セル関数: 1.1719秒

予想はしてましたが、再帰処理は少し遅いですね・・・(^^;;;。


セル関数は、セルで使えるDEC2HEXという関数をVBA内でApplication.Dec2Hex(123456)みたいにして使ったのですが、Applicationは無理にセル関数をVBAで呼び出すために計算速度が遅いだけで、恐らくセル関数でやればこれが最速だと思います。


ちなみに逆に16進数のABCDEFを10進数に直したら、 

  • 再帰処理: 0.7939秒
  • 通常処理: 0.3829秒
  • セル関数: 1.0231秒

でした。再帰が異様に遅いのは、恐らく再帰処理の問題ではなく、

"Mid(num16, 1, Len(num16) - 1)"

の文字列処理に時間がかかっているのではないかと思います。


ちなみに、計算速度はコンパイラがどういう最適化をしたかにも依存するのでこれだけで断言はできませんが、一般に再帰処理はメモリを多く使うので計算速度は遅いようです。



正直、n進数変換くらいだとそこまでソースがすっきりするわけでもないのですが、再帰処理って何だか頭良くなったような自己満足が得られて、ちゃんと動いたときに嬉しいんですよね(^^)。



ま、Excelは持ってさえいればプログラミングできますし、何より便利なとこは入力フィールドなどのGUIを設計しなくてもセル自体がインターフェースになる上、セル関数と併用することもできるのが魅力です。


ということで、ご興味あれば遊んでみてくださいませ。



いや、私は仕事で作ったソースを
ブログ用にわざわざ焼き直したわけですけど・・・ 


そこ、「仕事しろ!」とか言わない。