[VBA] 完全数・過剰数・不足数

[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 個の完全数を見つけ出します。

エクセルや数学に関するコメントをお寄せください