[VBA] 完全数・過剰数・不足数
この記事では、完全数・過剰数・不足数について説明し、VBA で完全数を探索する方法について解説します。
CDIVISOR関数
ある自然数 $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 」が返ります。
SDIVISOR関数
ある自然数 $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 」が返ります。
完全数/過剰数/不足数
自然数 $a$ を $S(a)$ によって次の 3 種類に分類することがあり、古来ギリシア時代から熱心に研究されてきました。
① $S(a)=2a$ が成り立つとき、すなわち $a$ 以外の約数の和が $a$ に等しいとき、$a$ を 完全数 (perfect number) とよびます。たとえば 6 の約数は 1, 2, 3, 6 であり、6 自身を除いた約数の和は
\[1+2+3=6\]
となるので 6 は完全数です。完全数はとても珍しい数です。
② $S(a)\gt 2a$ のとき、すなわち $a$ 以外の約数の和が $a$ より大きいとき、$a$ を 過剰数 または豊数 (abundant number) といいます。
③ $S(a)\lt 2a$ のとき、すなわち $a$ 以外の約数の和が $a$ より小さいとき、$a$ を 不足数 または輸数 (deficient number) とよびます。
SDIVISOR関数を使うと、その数字が完全数であるかどうかを判定することができます。たとえば
=SDIVISOR(28,1)
と入力すると「 28 」が返ってくるので 28 は完全数です。
=SDIVISOR(50,1)
と入力すると「 43 」が返ってくるので、50 は不足数であることがわかります。
完全数を探索するマクロ
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 個の完全数を見つけ出します。
エクセルや数学に関するコメントをお寄せください