【VBA】完全数の探索
ある自然数 $N$ が与えられたとき、その約数の個数を $T(N)$ という関数で表すことにします。たとえば 12 の約数は 1, 2, 3, 4, 6, 12 の計 6 個なので、
\[T(12)=6\]
となります。このような計算をさせるユーザー定義関数 CDIVISOR のプログラムは次のようになります(頭文字の C は Count の略、Divisor は約数です)。
'[VBA]約数の個数を求める関数 'エラー値を代入するため戻り値はVariant '(関数名のあとにデータ型を宣言しない) Function CDIVISOR(n As Long, Optional t As Boolean = False) Dim k As Long, m As Long m = n 'オプション引数がTrueのときは 'カウント上限値を1つ減らして 'n自身を約数としてカウントしない If t = True Then m = n - 1 End If Select Case n '指定引数nが0または負数ならばエラー Case Is <= 0 CDIVISOR = CVErr(xlErrNA) Case Else '1から順にnを割り切れるかどうか判定して '約数であるものだけカウントする For k = 1 To m If n Mod k = 0 Then s = s + 1 End If Next k CDIVISOR = s End Select End Function
CDIVISOR() をワークシートで使用するときはセルに
=CDIVISOR(N [,N自身を個数に含めるか否か])
という形式で入力します。N には自然数を指定してください。オプション引数に False または 0 を指定すると N 自身を約数に含めてカウントし、True または 1 を指定すると N 自身を個数から除きます。N = 12 で試してみましょう。
=CDIVISOR(12)
と入力すると、12 自身を含めた約数の個数「6」が返ります。
=CDIVISOR(12,1)
と入力すると、12 自身を除いた約数の個数「5」が返ります。
ある自然数 $N$ が与えられたとき、その約数の総和を $S(N)$ という関数で表すことにします。たとえば 12 の約数は 1, 2, 3, 4, 6, 12 なので、
\[S(12)=1+2+3+4+6+12=28\]
となります。このような計算をさせるユーザー定義関数 SDIVISOR のコードを載せておきます(頭文字の S は Sum の略、Divisor は約数です)。
'[VBA]約数の総和を求める関数 Function SDIVISOR(n As Long, Optional t As Boolean = False) Dim k As Long, m As Long m = n 'オプション引数がTrueのときは 'カウント上限を1つ減らして約数和からn自身を除く If t = True Then m = n - 1 End If Select Case n '指定引数nが0または負数ならばエラー Case Is <= 0 SDIVISOR = CVErr(xlErrNA) Case Else '1から順にnを割り切れるかどうか判定して約数だけsに加える For k = 1 To m If n Mod k = 0 Then s = s + k End If Next k SDIVISOR = s End Select End Function
SDIVISOR() をワークシートで使用するときは
=SDIVISOR(N [,N自身を加えるか否か])
と入力します。N には自然数を指定してください。オプション引数に False または 0 を指定すると N 自身を含めて和を計算し、True または 1 を指定すると N 自身を除いた和を計算します(後述するように完全数を調べるときは True を指定します)。N = 12 で試してみましょう。
=SDIVISOR(12)
と入力すると、12 自身を含めた約数の総和「28」が返ります。
=SDIVISOR(12,1)
と入力すると、12 自身を除いた約数の個数「16」が返ります。
$S(a)=2a$ が成り立つとき、すなわち $a$ 以外の約数和が $a$ に等しいとき、$a$ を完全数(perfect number)とよびます。たとえば 6 の約数は 1, 2, 3, 6 であり、6 自身を除いた約数の和は
\[1+2+3=6\]
となるので 6 は完全数です。完全数はとても珍しい数です。
SDIVISOR関数を使うと、その数字が完全数であるかどうかを判定することができます。たとえば
=SDIVISOR(28,1)
と入力すると「28」が返ってくるので 28 は完全数です。判定を自動化しましょう。SDIVISOR() を呼びだして完全数を見つけるマクロを載せておきます。
'[VBA]完全数の探索 Sub Search_Perfect() Dim k As Long For k = 1 To 10000 If k = SDIVISOR(k, 1) Then Debug.Print k; End If Next k End Sub
Search_Perfect() を実行すると 10000 までの数について判定を行い、「6 28 496 8128」という 4 個の完全数を見つけ出します。
エクセルや数学に関するコメントをお寄せください