【Excel VBA】試し割り法で高速素因数分解!入力値バリデーション付き堅牢関数の作り方
Excel VBAでちょっとした数値計算やアルゴリズムを実装したいとき、整数の「素因数分解」をパッと行えたら便利ですよね。
この記事では、VBAで素因数分解を効率的かつ安全に行うためのアルゴリズム(試し割り法)の解説と、そのまま標準モジュールに貼り付けて使える実践的なVBAコード・テスト結果をご紹介します。
1. 試し割り法(Trial Division)のアルゴリズム
今回は、素因数分解の最も基本的で直感的なアルゴリズムである試し割り法を使用しています。
- 2で割れるだけ割る:最小の素数である
2で割れるだけ繰り返し割り、割れた数を素因数として記録しながら元の数Nを小さくしていきます。 - 奇数のみ試す:
2で割れなくなったら、次は3, 5, 7...と奇数(2 ずつ加算)のみで割っていきます(2 以外の偶数値で割り切れることはないため、計算量を半減できます)。 - 判定の範囲:割る数
dについて、d * d <= N(dがNの平方根以下)の範囲まで調べれば十分です。ループ終了時にNが 1 より大きければ、その残ったN自体が最後の素因数となります。
2. VBAコード(標準モジュールに記述)
不正な入力(文字列、小数、1以下の数値など)に対するバリデーション(入力値チェック)もしっかり組み込んだ堅牢なコードです。
Option Explicit
' 素因数分解を行う関数
Public Function Factorize(ByVal inputVal As Variant) As String
' 1. 引数のバリデーション
If Not IsNumeric(inputVal) Then
Factorize = "エラー: 数値を入力してください。"
Exit Function
End If
Dim n As Double
n = CDbl(inputVal)
If n <> Fix(n) Then
Factorize = "エラー: 整数を入力してください。"
Exit Function
End If
If n < 2 Then
Factorize = "エラー: 2以上の正の整数を入力してください。"
Exit Function
End If
' 2. 試し割り法による計算
Dim result As String
Dim divisor As Double
divisor = 2
Do While divisor * divisor <= n
' Double型での余り判定
If n - Fix(n / divisor) * divisor = 0 Then
If result <> "" Then result = result & " * "
result = result & CStr(divisor)
n = n / divisor
Else
If divisor = 2 Then
divisor = 3
Else
divisor = divisor + 2 ' 奇数のみ進める
End If
End If
Loop
' 最後に残った数が1より大きければ素因数として追加
If n > 1 Then
If result <> "" Then result = result & " * "
result = result & CStr(n)
End If
Factorize = result
End Function
' テスト実行用プロシージャ (イミディエイトウィンドウに出力)
Public Sub Test_Factorize()
Debug.Print "=== 正常系のテスト ==="
Debug.Print "12 -> " & Factorize(12) ' 2 * 2 * 3
Debug.Print "84 -> " & Factorize(84) ' 2 * 2 * 3 * 7
Debug.Print "97 -> " & Factorize(97) ' 97 (素数)
Debug.Print "360 -> " & Factorize(360) ' 2 * 2 * 2 * 3 * 3 * 5
Debug.Print "999999 -> " & Factorize(999999) ' 3 * 3 * 3 * 7 * 11 * 13 * 37
Debug.Print "8589934592 -> " & Factorize(8589934592#) ' 2が33個
Debug.Print vbCrLf & "=== 異常系(エラーチェック)のテスト ==="
Debug.Print "1 -> " & Factorize(1) ' エラー
Debug.Print "0 -> " & Factorize(0) ' エラー
Debug.Print "-10 -> " & Factorize(-10) ' エラー
Debug.Print "3.14 -> " & Factorize(3.14) ' エラー
Debug.Print "abc -> " & Factorize("abc") ' エラー
End Sub
' 素因数分解を行う関数
Public Function Factorize(ByVal inputVal As Variant) As String
' 1. 引数のバリデーション
If Not IsNumeric(inputVal) Then
Factorize = "エラー: 数値を入力してください。"
Exit Function
End If
Dim n As Double
n = CDbl(inputVal)
If n <> Fix(n) Then
Factorize = "エラー: 整数を入力してください。"
Exit Function
End If
If n < 2 Then
Factorize = "エラー: 2以上の正の整数を入力してください。"
Exit Function
End If
' 2. 試し割り法による計算
Dim result As String
Dim divisor As Double
divisor = 2
Do While divisor * divisor <= n
' Double型での余り判定
If n - Fix(n / divisor) * divisor = 0 Then
If result <> "" Then result = result & " * "
result = result & CStr(divisor)
n = n / divisor
Else
If divisor = 2 Then
divisor = 3
Else
divisor = divisor + 2 ' 奇数のみ進める
End If
End If
Loop
' 最後に残った数が1より大きければ素因数として追加
If n > 1 Then
If result <> "" Then result = result & " * "
result = result & CStr(n)
End If
Factorize = result
End Function
' テスト実行用プロシージャ (イミディエイトウィンドウに出力)
Public Sub Test_Factorize()
Debug.Print "=== 正常系のテスト ==="
Debug.Print "12 -> " & Factorize(12) ' 2 * 2 * 3
Debug.Print "84 -> " & Factorize(84) ' 2 * 2 * 3 * 7
Debug.Print "97 -> " & Factorize(97) ' 97 (素数)
Debug.Print "360 -> " & Factorize(360) ' 2 * 2 * 2 * 3 * 3 * 5
Debug.Print "999999 -> " & Factorize(999999) ' 3 * 3 * 3 * 7 * 11 * 13 * 37
Debug.Print "8589934592 -> " & Factorize(8589934592#) ' 2が33個
Debug.Print vbCrLf & "=== 異常系(エラーチェック)のテスト ==="
Debug.Print "1 -> " & Factorize(1) ' エラー
Debug.Print "0 -> " & Factorize(0) ' エラー
Debug.Print "-10 -> " & Factorize(-10) ' エラー
Debug.Print "3.14 -> " & Factorize(3.14) ' エラー
Debug.Print "abc -> " & Factorize("abc") ' エラー
End Sub
3. 実行結果(イミディエイトウィンドウ)
上記の Test_Factorize を実行すると、正常系・異常系ともに意図した通りに出力されます。
=== 正常系のテスト ===
12 -> 2 * 2 * 3
84 -> 2 * 2 * 3 * 7
97 -> 97
360 -> 2 * 2 * 2 * 3 * 3 * 5
999999 -> 3 * 3 * 3 * 7 * 11 * 13 * 37
8589934592 -> 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
=== 異常系(エラーチェック)のテスト ===
1 -> エラー: 2以上の正の整数を入力してください。
0 -> エラー: 2以上の正の整数を入力してください。
-10 -> エラー: 2以上の正の整数を入力してください。
3.14 -> エラー: 整数を入力してください。
abc -> エラー: 数値を入力してください。
12 -> 2 * 2 * 3
84 -> 2 * 2 * 3 * 7
97 -> 97
360 -> 2 * 2 * 2 * 3 * 3 * 5
999999 -> 3 * 3 * 3 * 7 * 11 * 13 * 37
8589934592 -> 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2 * 2
=== 異常系(エラーチェック)のテスト ===
1 -> エラー: 2以上の正の整数を入力してください。
0 -> エラー: 2以上の正の整数を入力してください。
-10 -> エラー: 2以上の正の整数を入力してください。
3.14 -> エラー: 整数を入力してください。
abc -> エラー: 数値を入力してください。
VBAでちょっとした数学的処理を行いたいときや、アルゴリズムの基礎を実装する際の参考にしてみてください!
PR