オーロラさんの勉強帳

IT企業勤務。データベース、Excel、Excel VBA、ネットワーク、LinuxなどIT関連のことを主に書いていきます。少しでもお役に立てたら幸いです。

【Excel VBA】再帰呼出しで最大公約数を求める(ユークリッドの互除法)

プログラムが自分自身を呼び出す処理のことを「再帰呼出し」といいます。
今回は再帰呼出しを使って、2つの数の最大公約数を求める方法を解説します。
最大公約数を求めるために、今回は『ユークリッドの互除法』と呼ばれるアルゴリズムを使います。

再帰呼出しの解説は以下の記事も参照ください。
auroralights.jp


最大公約数を求めるのVBAコード

以下は「48」と「20」の最大公約数を求めるVBAコードです。

Sub sampleCall()
    MsgBox sampleGcd(48, 20)
End Sub

Function sampleGcd(ByVal m As Long, ByVal n As Long) As Long
    If n = 0 Then
        sampleGcd = m
    Else
        sampleGcd = sampleGcd(n, m Mod n)
    End If
End Function

※Sub sampleCall内のMsgBox sampleGcd(48, 20)の()内の数字「48,20」を任意の2つの数字に変えると、その数字の最大公約数を求めることができます。


処理を考える

上記の最大公約数を求めるVBAの処理を見ていきます。

再帰呼出し

1~2行目:Subプロシージャ「sampleCall」からFunctionプロシージャ「sampleGcd」を呼び出し、引数48と20を渡します。
5行目:48を「m」、20を「n」に格納します。
6行目:IF文の条件分岐です。n = 0ではないので、9行目に移ります。
9行目:Functionプロシージャ「sampleGcd」を再帰呼出し、その際に「n」と「m mod n (mをnで除算した余り)」を引数として渡します。
5行目:渡された引数「n」を「m」、「m mod n」を「n」に格納します。

以降は「n」が「0」になるまで、再帰呼出しでFunctionプロシージャ「sampleGcd」の処理を繰り返します。「n」が「0」になった時点の「m」を返り値として、Functionプロシージャ「sampleGcd」から呼び出し元のSubプロシージャ「sampleCall」に渡し、メッセージボックスに表示して処理を終えます。

引数「m」と「n」の変化


参考情報:ユークリッドの互除法、最大公約数、GCD関数

ユークリッドの互除法

ユークリッドの互除法は、2つの自然数a、bの最大公約数を求める方法です。(詳細な内容は難しいので割愛します)

1.「a」を「b」で割る。余り「r」を求める
2.「b」を1.で求めた「r」で割る。その余り「r1」を求める
3.「r」を2.で求めた「r1」で割る、その余り「r2」を求める
4.「r1」を3.で求めた「r2」で割る、その余り「r3」を求める
・・・・
余りが「0」になる(割り切れる)まで繰り返します。(必ず割り切れます)
余りが「0」になったときの割る数が最大公約数になります。

以下は500と75の最大公約数を求め方です。

最大公約数

2つ以上の数を割り切る数の中で、共通している数かつ、最も大きい数を最大公約数といいます。
最大公約数を理解するには、約数、公約数を理解する必要があります。

  • 約数:ある1つの正の整数を割り切る数
  • 公約数:2つ以上の正の整数に共通な約数
  • 最大公約数:公約数の中で一番大きな数

以下画像では10と12の最大公約数を考えています。

約数・公約数・最大公約数

GCD関数

Excelのワークシート関数『GCD関数』を使うと、最大公約数を求めることができます。

■GCD関数の書式
=GCD(数値1,数値2[,・・・・・,数値255])

GCD関数の利用例(=GCD(C2:D2)と引数にセル範囲を指定)



お読みいただきありがとうございました。

【Excel VBA】再帰呼出しをVBAで試してみる ~再帰呼出しの動きをわかりやすく解説~

プログラムが自分自身を呼び出す処理のことを「再帰呼出し」といいます。
実際にVBAのコードで「再帰呼出し」の動きをわかりやすく解説します。

階乗を求める再帰呼出しのVBAコード

4の階乗を求めるVBAのコードです。
FunctionプロシージャのsampleRecursiveで「再帰呼出し」にて、4の階乗を求めています。

Sub sampleCall()
  MsgBox sampleRecursive(4)
End Sub

Function sampleRecursive(ByVal n As Long) As Long
    If n <= 1 Then
        sampleRecursive = 1
    Else
        sampleRecursive = n * sampleRecursive(n - 1)
    End If
End Function

※Sub sampleCallのMsgBox sampleRecursive(4)の()内の数字「4」を任意の数字に変えると、その数字の階乗を求めることができます。


上記コードを動かしてみると、4の階乗(4×3×2×1)の24がメッセージボックスで表示されます。


再帰呼出しの動作を画像で分かりやすく解説

以下の画像は再帰呼出しの前半部分の解説画像です。
Subプロシージャ「sampleCall」からFunctionプロシージャ「sampleRecursive」を呼び出します。その際に引数として「4」を渡します。
Functionプロシージャ「sampleRecursive」で自分自身を呼出す際は、3、2、1と引数を渡していきます。

再帰呼出し

以下の画像は、再帰呼出しの後半部分の解説画像です。
『sampleRecursive = n * sampleRecursive(n - 1)』『sampleRecursive(n - 1)』に返り値(1、2、6)を返して、階乗を計算していきます。
※2*1⇒3*2⇒4×6で24求めています。
そして、再帰呼出しで求めた24をSubプロシージャ「sampleCall」に返して、メッセージボックスに表示しています。

再帰呼出し


4の階乗を再帰呼出しで求める動作の流れは以下の通りです。

再帰呼出し 4の階乗

再帰呼出しの動作を考える(文字ベース)

大きな動きは以下の図の通りです。上記では画像ベースで説明したので、テキストベースで1つずつの処理を解説します。

再帰呼出し

<Subプロシージャ:sampleCall>
1~2:Subプロシージャ「sampleCall」からFunctionプロシージャ「sampleRecursive」を呼び出します。その際に引数として4を渡します。

<FunctionプロシージャsampleRecursive>
4:Functionプロシージャ「sampleRecursive」でnには4が渡されています。
5:IF文でnが1以下かどうかで処理を分岐しています。(n=4なので8行目に移動)
8:sampleRecursive = n * sampleRecursive(n - 1)では、sampleRecursive =4*sampleRecursive(3)となります。sampleRecursive(3)で自分自身のFunctionプロシージャ「sampleRecursive」を呼び出します。
その際、引数に3を渡します。

引数に3を渡したFunctionプロシージャ「sampleRecursive」でも、8行目でさらに自分自身のFunctionプロシージャ「sampleRecursive」を呼び出します。
その際、引数に2を渡します。
引数に2を渡したFunctionプロシージャ「sampleRecursive」でも、8行目でさらに自分自身のFunctionプロシージャ「sampleRecursive」を呼び出します。
その際、引数に1を渡します。

引数に1を渡したFunctionプロシージャ「sampleRecursive」では、6行目でsampleRecursive=1で返し値として1を格納。
9~10行目のEnd If、End Functionで呼出し元に返り値1を返します。

呼出し元は「sampleRecursive = 2 * sampleRecursive(2 -1)」の『sampleRecursive(2 -1)』です。sampleRecursive(2 -1)に返り値1が入るので、「sampleRecursive = 2 * 1」(返り値が2)となります。
9~10行目のEnd If、End Functionで呼出し元に返り値に2を返します。

呼出し元は「sampleRecursive = 3 * sampleRecursive(3 -1)」の『sampleRecursive(3 -1)』です。
sampleRecursive(3 -1)に返り値2が入るので、「sampleRecursive = 3 * 2」(返り値が6)となります。
9~10行目のEnd If、End Functionで呼出し元に返り値に6を返します。

呼出し元は「sampleRecursive = 4 * sampleRecursive(4 -1)」の『sampleRecursive(4 -1)』です。
sampleRecursive(4 -1)に返り値6が入るので、「sampleRecursive = 4 * 6」(返り値が24)となります。
9~10行目のEnd If、End Functionで呼出し元に返り値に24を返します。

呼出し元Subプロシージャ「sampleCall」のMsgBox sampleRecursive(4)の『sampleRecursive(4)』です。
メッセージボックスに24を表示して、処理を終わります。


以上、再帰呼出しの解説です。
お読みいただきありがとうございました。

【Excel】便利な『オートカルク機能』 ~データの個数、合計値、平均、最小値、最大値を一瞬で確認できる~

『通勤のすきま時間で学ぶ仕事術』を紹介するシリーズです。
今回はExcelで、データの個数や合計値などを今すぐに確認したいときに使える『オートカルク機能』を紹介します。

オートカルク機能とは

オートカルク機能選択したセル範囲のデータの個数、数値の個数、合計値、平均、最小値、最大値をステータスバーに表示してくれる便利な機能です。
データの集計時の確認やデータの整合性の確認などで使います。
使い方はセル範囲を選択するだけなのでとても簡単です。


以下の画像ではセル「B3:D10」を選択し、ステータスバーに選択したセル範囲「B3:D10」の平均・データの個数・最小値・最大値・合計が表示されています。

オートカルク機能のサンプル画像
オートカルク機能

オートカルク機能でステータスバーに表示する項目を設定する

オートカルク機能でステータスバーに表示する項目は、ステータスバー上で右クリックして表示されるメニューの「平均」「データの個数」「数値の個数」、「最小値」、「最大値」、「合計」から設定できます。

オートカルク機能の設定
オートカルク機能の設定

オートカルク機能の使用例

選択した範囲の平均、データの個数、数値の個数、最小値、最大値、合計を簡単に確認できるので、報告書の作成などでデータを集計しているときに、データが正しいかどうかの確認などで使うことができます。

以下の画像ではセルE11の値が正しいことを確認しています。

資料を作成する際に、数式のセル範囲がずれていたり、数値が間違っていたりすることがあるので、オートカルク機能を使って素早くチェックをします。


以下の画像のように単純にデータの個数を確認することも多いです。

データベースやシステムから大量のデータをExcelにおとしたときに、データが全件Excelにあるか(データベースやシステムの件数とExcelのデータ件数が同じかどうか)を確認するためにオートカルク機能を使うことも多いです。
※データが大量にある場合、途中までしかダウンロードできていないことがあるため、件数の確認をすることがあります。


以上、オートカルク機能の紹介でした。
簡単で便利な機能ですので、ぜひ活用してみてください。