次の素数を取得するFucntion

次の素数を取得するFunction

数字を受け取って、その数字よりも大きい最小の素数を返すメソッドを作った。

コード

リスト1 標準モジュール
Private Function getNextPrimeNumber( _
             ByVal targetNumber As Long) As Long
  Dim ret As Long
  ret = targetNumber + 1
  Do While Not isPrimeNumber(ret)
    ret = ret + 1
  Loop
  getNextPrimeNumber = ret
End Function

見てのとおり、途中、素数判定には自作のisPrimeNumberメソッドを用いている。

isPrimeNumberメソッドのコードをリスト2に示す。

スト2 標準モジュール
Option Explicit

Private Const MAX_NUMBER As Long = (2 ^ 31) - 1
Private Const OVER_FLOW_NUMBER As String = _
  "引数が大きすぎます。"
Private Const NOT_NATURAL_NUMBER As String = _
  "引数は自然数でなければいけません。"

Public Function isPrimeNumber( _
            ByVal targetNumber As Long) As Boolean
  isPrimeNumber = False
  '引数が不正だったらエラーを吐く'
  Call raiseErrorIfInvalidArg(targetNumber)
  '1だったらFalse'
  If targetNumber = 1 Then Exit Function
  '2だったらTrue'
  If targetNumber = 2 Then GoTo Finalizer
  '中央の値までループして合成数判定'
  Dim turningPoint As Long
  'ループするのは平方根の近似値までで良い'
  turningPoint = Int(Sqr(targetNumber))
  Dim i As Long
  For i = 2 To turningPoint
    If targetNumber Mod i = 0 Then
'      Debug.Print i & "で割り切れる。"'
      Exit Function
    End If
  Next
Finalizer:
  isPrimeNumber = True
End Function

Private Sub raiseErrorIfInvalidArg( _
              ByVal targetNumber As Long)
  '1よりも小さな数字を受け取ったらエラーを吐く'
  If targetNumber < 1 Then _
    Call Err.Raise(Number:=10001, _
                   Source:="Arg is not natural number.", _
                   Description:=NOT_NATURAL_NUMBER)
  'オーバーフローする場合エラーを吐く'
  If targetNumber > MAX_NUMBER Then _
    Call Err.Raise(Number:=10002, _
                   Source:="Arg will be over flow.", _
                   Description:=OVER_FLOW_NUMBER)
End Sub

引数がおかしかったときにはエラーを吐くようにしている。

2の31乗マイナス1(2147483647)までならオーバーフローしなかったので、最大値を2の31乗マイナス1にしておいた。

実験

標準モジュールのオブジェクト名を「MathUtil」にしている(本当は「Math」にしたかったんだが名前が衝突するので……。)ので、

?MathUtil.getNextPrimeNumber([引数])

の形で、イミディエイト・ウインドウ上で実行。

f:id:akashi_keirin:20190601203804j:plain

ちゃんと取得できている……よね?

おわりに

これで、素因数分解をするプログラムを書く準備ができた。

面白くなってきたぞ。

仕事の役には立たないだろうけど。