VBA では割り算の剰余を求めるために、関数ではなく Mod 演算子が用意されています。エクセルの MOD関数とは少し使い勝手が異なりますが、基本的な考え方は同じです。
Mod演算子
VBA の Mod は モジュロ演算 (剰余演算) を実行します。
a を b で割ったときの余りを求めるときは「a Mod b」のように記述します。たとえば 11 を 4 で割ったときの余りを求めるには「11 Mod 4」ます。
'[VBA] Mod演算子のサンプルコード[1] Sub Modulo_1() Dim i As Integer i = 11 Mod 4 Debug.Print i End Sub 'Modulo_1の実行結果: '3
Mod 演算子のステートメント「a Mod b」において b が 0 の場合は( 0 で割ることになるので)エラーになるのは言うまでもありません。
また、a や b が整数でない場合はエラーにはなりませんが、銀行丸め によって強制的に整数に変えて計算を続行します。銀行丸めは四捨五入とよく似ています。10.3 であれば 10 に丸め、10.7 であれば 11 に丸めます。ただし 10.5 のときは「偶数である」10 のほうへ丸められます。 11.5 であれば「偶数である」12 のほうへ丸められます。たとえば 「11 Mod 2.5」と書くと、得られる値は 11 ÷ 2 を計算して余り「 1 」を得ます(四捨五入であれば 11 ÷ 3 の余りは 2 となるはずです)。実際に「11 Mod 2.5」計算させるマクロを載せておくので試してみてください。
'[VBA] Mod演算子のサンプルコード[2] Sub Modulo_2() Dim i As Integer i = 11 Mod 2.5 Debug.Print i End Sub 'Modulo_2の実行結果: '1
整数論の話になりますが、$11$ を $-2$ で割ったときの商は $-5$ ですから、
\[11=(-5)\times(-2)+1\]
のように書くことができます。この $+1$ という部分が余りですから、VBA で「11 Mod -2」とすれば「1」を得ることになります。同じように $-11$ を $3$ で割ったときの商は $-3$ なので、
\[-11=(-3)\times 3 -2\]
と書けて、余りが $-2$ であることがわかります。VBA で「-11 Mod 3」と記述すると「-2」が返ります。実際のコードは次のようになります。
'[VBA] Mod演算子のサンプルコード[3] Sub Modulo_3() Dim i As Integer i = -11 Mod 3 Debug.Print i End Sub 'Modulo_3の実行結果: '-2
ベキ乗の除算の余りを求める手順
たとえば VBA の Mod 演算子で $2^{100}$ を $13$ で割ったときの余りを求めようと思って、次のようなコードを書いたとします。
'[VBA] Mod演算子のサンプルコード[4]
'2^100を13で割ったときの剰余を計算するマクロ
Sub Modulo_4()
Dim x As Long
Debug.Print (2 ^ 100) Mod 13
End Sub
Modulo_4() を実行するとオーバーフローしてしまいます。巨大数 $2^{100}$ の演算が VBA の処理能力を遥かに超えてしまうからです。しかし、数論の合同式を上手く活用すると、$a^k$ のような整数のベキ乗を除算したときの余りはたった数行のコードで計算できます。アルゴリズムの流れを確認するために、例として $5^8$ を $7$ で割ったときの余りを合同式で求めてみます。計算には合同式の基本公式
\[a\equiv b,\:\:c\equiv d\quad\Longrightarrow\quad ab\equiv cd\quad\pmod m\]
を用います。
\[5\equiv 5\quad\pmod 7\]
はもちろん成り立ちます。両辺に $5$ を掛けると
\[5^2\equiv 25\equiv 4\quad\pmod 7\]
となります。以下同様に両辺に $5$ を掛け続けます。
\[\begin{align*}&5^3\equiv 20\equiv 6&\quad\pmod 7\\[6pt]&5^4\equiv 30\equiv 2&\quad\pmod 7\\[6pt]&5^5\equiv 10\equiv 3&\quad\pmod 7\\[6pt]&5^6\equiv 15\equiv 1&\quad\pmod 7\\[6pt]&5^7\equiv 5&\quad\pmod 7\\[6pt]&5^8\equiv 25\equiv 4&\quad\pmod 7\end{align*}\]
よって余りは $4$ となります。この方法で $a^k$ を除算したときの余りを計算する MOD_P 関数のコードを載せておきます。
'[VBA] Mod演算子のサンプルコード[5] 'a^kをmで割ったときの余りを計算する関数 Function MOD_P(a As Long, k As Long, m As Long) Dim i As Long, x As Long x = 1 For i = 1 To k 'xにaを掛けてmで割って余りを求める x = a * x Mod m Next i MOD_P = x End Function
MOD_P 関数をワークシートで使用するときは
=MOD_P(a,k,m)
と入力します。たとえば $5^8$ を $7$ で割ったときの余りを計算させるときは
=MOD_P(5,8,7)
と入力すると「4」が返ります。もっと大きな数で試してみましょう。 $2^{100}$ を $13$ で割ったときの余りを計算させてみます。
=MOD_P(2,100,13)
と入力すると「3」が返ります。
エクセルや数学に関するコメントをお寄せください
【VBA】Mod function
The Mod function in VBA is an arithmetic operator that returns the remainder of a division operation between two integers. The syntax for using the Mod function in VBA is “Mod(dividend, divisor)”. For example, Mod(10, 3) would return 1 since the remainder of dividing 10 by 3 is 1.The Mod function is commonly used in loop operations to execute a certain action after a specific number of iterations. By checking if Mod(n, m) equals 0, where n is the loop counter and m is the desired frequency of the action, the action can be executed every m iterations.Overall, the Mod function in VBA is a useful tool for performing arithmetic operations involving remainders and controlling loop operations.
【AI連載小説】数学のリズム、エクセルの旋律(7)
「VBAのModの使い方をレクチャーします」
部室の中で、真琴は月子にExcel VBAのMod演算子の使い方を教えていました。Excelのデータ処理において、Mod演算子は割り算の余りを求める際に使われます。
真琴:月子、今日はMod演算子の使い方を教えてあげるよ。これは割り算の余りを求めるために使うんだ。
月子:(興味津々)わかった!具体的にどうやって使うんですか?
真琴:例えば、数値を2で割ったときの余りを求める場合、Mod演算子を使うんだ。こんな感じだよ。
これで、数値を2で割ったときの余りが求められるんだ。試しに実行してみて。
(月子は興味津々ながら、Excel VBAエディタでコードを打ち込み、実行ボタンをクリックした。すると、ポップアップが表示されて計算結果が表示された。)
月子:(にっこり笑って)わかった!これなら使えそうだね。でも、なんでMod演算子を使うんですか?
真琴:Mod演算子は周期的な処理や、ある範囲内での処理に使えるんだ。例えば、曜日を求めるとか、データを周期的に処理するときに便利だよ。
月子:なるほど。実用的な使い方ができそうですね。
真琴:そうだ。他にも、Mod演算子は周期的な処理にも使える。例えば、1から10までの数を3で割ったときの余りを求めると、1, 2, 0, 1, 2, 0…と繰り返されるんだ。これを利用して周期的な処理を行うことができる。
これで、1から10までの数を3で割ったときの余りが表示されるよ。面白いだろ?
月子:(笑顔で)すごい!確かにMod演算子は奥が深いですね。これでより複雑なプログラムが組めそうです。