第5講 Subプロシージャ
第5話 素数列挙Subプロシージャ
素数列挙マクロコード例
Dim cn As Long
Private Sub CommandButton1_Click()
Dim n As Long, i As Long
cn = 0
n = Cells(5, 2)
For i = 2 To n
f (i)
Next
Cells(7 + Int(cn / 20), 2) = "素数個数"
Cells(7 + Int(cn / 20), 3) = cn
End Sub
Sub f(n As Long)
Dim i As Long, r As Long
If n = 2 Then
Cells(6 + Int(cn / 20), 2 + (cn Mod 20)) = n
cn = cn + 1
Exit Sub
End If
If n Mod 2 = 0 Then
Exit Sub
End If
r = Sqr(n)
For i = 3 To r Step 2
If n Mod i = 0 Then
Exit Sub
End If
Next
Cells(6 + Int(cn / 20), 2 + (cn Mod 20)) = n
cn = cn + 1
End Sub
Private Sub CommandButton2_Click()
Columns("B:U").Select
Selection.ClearContents
Cells(1, 1).Select
End Sub
解説
今回は、素数であるか判定し素数である場合のみ表示させています。
注目は
Cells(6 + Int(cn / 20), 2 + (cn Mod 20)) = n
cn = cn + 1
の2行です。
Int(cn / 20)は、素数総数cnを20で割った商であり、
cn Mod 20は20で割った余りです。
このようにすると、20個ずつ
表示させることが出来ます。
もし30個ずつ表示させたいときは
Cells(6 + Int(cn / 30), 2 + (cn Mod 30)) = n
とします。要するに、ピンクの数字を変えればよいのです。
今回、グローバル変数を用意しましたが、
次のようにすればローカル変数のみでも出来ます。
Private Sub CommandButton1_Click()
Dim n As Long
n = Cells(5, 2)
f (n)
End Sub
Sub f(n As Long)
Dim cn As Long
Dim i As Long, j As Long, r As Long
cn = 0
For i = 2 To n
If i = 2 Then
Cells(6 + Int(cn / 30), 2 + (cn Mod 30)) = i
cn = cn + 1
End If
If i Mod 2 = 0 Then
GoTo owari
End If
r = Sqr(i)
For j = 3 To r Step 2
If i Mod j = 0 Then
GoTo owari
End If
Next
Cells(6 + Int(cn / 20), 2 + (cn Mod 20)) = i
cn = cn + 1
owari:
Next
Cells(7 + Int(cn / 20), 2) = "素数個数"
Cells(7 + Int(cn / 20), 3) = cn
End Sub
Private Sub CommandButton2_Click()
Columns("B:AE").Select
Selection.ClearContents
Cells(1, 1).Select
End Sub
GoTo owariは行ラベルowariへ飛べという命令です。
BASICの頃、スパゲッティプログラムの元凶としてやり玉に挙げられたGoTo文ですが、
次の原則を守れば、使ってもよいと思います。
@ 飛ぶ箇所は一カ所のみ
A 必ず下へ飛ぶ
さて、前者と後者ではどちらがわかりやすいでしょうか。圧倒的に前者ではないでしょうか。後者は
For i = 2 To n
If i = 2 Then
Cells(6 + Int(cn / 30), 2 + (cn Mod 30)) = i
cn = cn + 1
End If
If i Mod 2 = 0 Then
GoTo owari
End If
r = Sqr(i)
For j = 3 To r Step 2
If i Mod j = 0 Then
GoTo owari
End If
Next
Cells(6 + Int(cn / 20), 2 + (cn Mod 20)) = i
cn = cn + 1
owari:
Next
の部分が2次元ループになっています。
それに対して前者では、
r = Sqr(n)
For i = 3 To r Step 2
If n Mod i = 0 Then
Exit Sub
End If
Next
と1次元ループです。
理由は、Private Sub CommandButton1_Clickの部分でもう一つの次元
For i = 2 To n
f (i)
Next
を受け持っているからです。
つまり、メインプロシジャとSubプロシージャで次元を分担して受け持っているわけです。
次元ごとに分担させれば、3次元や4次元であっても簡単にできます。
もし、4次元を1つのプロシージャに担当させるとすると、頭が混乱してしまいますが、
4つのプロシージャを用意すれば、すべてが1次元ですから、かなりすっきりします。
Funcitonプロシージャの終わりのところで、プロシージャを使用する意義をまとめるつもりですが、
意義の1つは次元を分割することによってわかりやすくなるという点です。
わかりにくい後者を持ち出した理由は、引数は複数指定できることを説明したかったからです。
今回は、後者を参考にして範囲は、1から終わりの数までではなく、
はじめも終わりも指定できるように改良したいと思います。
f (n)は、今回は2つの引数f(引数1,引数2)を持ちます。すると、プロシージャの宣言も
Sub f(引数1 As 型,引数2 As 型)とします。
例えば引数がhとoのときは、
次のようにしてプロシージャを呼び出します。
f h,o
です。
C言語などではf(h,o)すっきりした呼び出しになりますが、VBではこのような呼び出しは認めていません。
気持ちが悪いのですが、f h,oと書くしかありません。
尚、引数が1つときのf (n)は、f n でもよいのです。
私の好みは圧倒的にf(n)です。
ですから、f h,oもf(h,o)と書きたいのですがだめなのです。
第4話へ 第6話へ
vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
数学研究室に戻る