どうも!リョクちゃです。
今回は任意の数字の各桁を抽出していき、抽出した桁をそれぞれ足し合わせて
和を求める関数を自作していきます。
関数を作成するポイントや考え方を紹介出来たらなと思っています。
ちなみに前回はこちら
前回記事にした再帰処理の考え方も今回織り込んでいきます。
目次
関数化の考え方
考え方としては、以下のようなポイントが経験上関数化できると考えています。
- 同じような処理が続く場合は関数化できないか考える
- 最初は直書きし、後でまとめられるとこは関数化を考える
- 関数の中に関数を無暗に作らない
- 階層が深くなりそうなところは関数化を考える
同じような処理が続く場合は関数化できないか考える
コードの見やすさと保守性も考えた結果、
同じような処理が何個も至る所にあると修正が発生した場合
全ての箇所を修正していかなくてはならないので、
コードの再修正に大幅な時間がかかってしまい効率が悪いです。
なので、同じような処理が増える場合は先に関数化できないか考えてみましょう。
最初は直書きし、後でまとめられるとこは関数化を考える
いきなり関数化を考えろと言われても難しいので、
まずは素直に直書きをしていき、1でも述べた同じような処理がないかや
関数化できないかなどを探し、見つけたら関数に直していきましょう。
最初は地道にコツコツやるのが考え方も身につくし、タイピングも早くなっていきます(笑)
関数の中に関数を無暗に作らない
意外と慣れてくるとよくやりがちなのですが、
関数の中に関数をいれてしまうことです。これは考え方というよりは
あまりしない方がよい書き方ですね。
ただし、処理によっては関数の中に関数を入れた方が効率よい場合もあるので
ここはケースバイケースで対応していきましょう。
なぜ、関数の中に関数を入れるのがあまりよくないというと、
個人的には、単純にコードが見づらく処理が追いづらくなってきてしまうからです。
まさに迷路です……。関数化はいい方法なのですが、関数化しなくてもいい処理を
関数化してしまうとかえってマイナスになります。
負の連鎖の始まりです。
階層が深くなりそうなところは関数化を考える
3と重複しますが
これも1つの関数内で条件分岐や繰り返し処理が深くなりすぎると、
見づらくなる原因のひとつ+途中でどこを追っているかわからなくなる原因の
1つになります。
階層(条件分岐や繰り返い処理の中に条件分岐や繰り返し処理を入れていく。)は関数内で
最低でも5~6個ぐらいにとどめて深くなりそうなら関数に分割するのが良いでしょう。
と考え方は、多種多様、十人十色ですが、これらを意識して書くようにしておけば
上達していくのではないでしょうか。
各桁の和を計算する際の考え方
関数化するにあたり各桁の和を計算する考え方ですが、
例えば、325という数字の各桁は、それぞれ
- 百の位が3
- 十の位が2
- 一の位が5
となっています。
これをそれぞれ足しわせると、
$$3 + 2 + 5 = 10$$
となり、325の各桁を足し合わせた解は、10となることがわかります。
各桁を抽出するには、以下の式を使って求めることができます。
以降、nが0になるまで①~②を繰り返していきます。
※ あまり x が桁になります。
例えば325を上記の式に当てはめる場合、
- 325 / 10 = 32 あまり 5
- 32.5 / 10 = 3 あまり 2
- 3 / 10 = あまり 3
①~③のあまりをそれぞれ足し合わせていくと、10になります。
これを関数化しないでコードで書いていくと、
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Dim num As Integer = 325 ' 計算する変数 Dim a As Integer = 0 ' 百の位の桁を格納する変数 Dim b As Integer = 0 ' 十の位の桁をを格納する変数 Dim c As Integer = 0 ' 一の位の桁をを格納する変数 a = num Mod 10 num = Math.Floor(num / 10) Console.WriteLine(a) If num > 0 Then b = num Mod 10 num = Math.Floor(num / 10) Console.WriteLine(b) If num > 0 Then c = num Mod 10 num = Math.Floor(num / 10) Console.WriteLine(c) End If End If Console.WriteLine(a + b + c) |
こんな感じですかね、素直に書いていくと。
ちなみに3桁の計算にしか対応していません。。。
関数化してみる
考え方を活かして、今回は2通りの関数の作成法を紹介していきます。
関数化①
まず、素直に書いた関数に工夫を加え、さらに3桁以上にも対応できるようにしていきます。
1 2 3 4 5 6 7 8 |
Private Function digitSum(ByVal n As Integer) As Integer Dim rec As Integer = 0 While (n > 0) rec += n Mod 10 n = Math.Floor(n / 10) End While Return rec End Function |
与えられた数字が0になるまで割り、つど余りを変数recに足していっています。
再帰処理を考えた関数化②
①で紹介した関数化とは切り口を変えて、再帰処理を交えた場合の関数化もしてみます。
再帰処理は自分自身を呼び出す関数の処理をいいました。
コードで書いていくと、
1 2 3 4 5 6 7 |
Private Function digitSum(ByVal n As Integer) As Integer Dim rec As Integer = 0 If n > 0 Then rec += n Mod 10 + digitSum(Math.Floor(n / 10)) End If Return rec End Function |
これが再帰処理を交えた各桁の和を計算する関数化になります。
①と比べてシンプルかつ、1行短くできました。
①のWhile下の処理を1行にしたのが再帰処理の条件文下の処理となっています。
このようにして考え方次第では、様々な関数の作成方法があります。
結果が同じになれば、自分なりの関数を作ってみるのもいいと思います。
ただし、あまりにも処理が遅い等はバグの問題にもなりかねないので
それなりの精度を持った関数になるように作りましょう。
まとめ
任意の数字の各桁の和を足していく関数を作成していきました。
関数化をしていく上で、考え方のポイントは
- 同じような処理が続く場合は関数化できないか考える
- 最初は直書きし、後でまとめられるとこは関数化を考える
- 関数の中に関数を無暗に作らない
- 階層が深くなりそうなところは関数化を考える
といったポイントが経験上あります。
一方で、関数を増やし過ぎるのもかえって見づらくなる原因となるので、
最低限使用性の高いコードを関数化するようにしましょう。
ある程度関数が出来上がってきたらクラス化してしまうのも手でしょう。
例えば、テーマに基づいた計算をする関数が多い場合は
それだけのクラスを作ってみましょう。
クラス化すると再利用性にも富んで一気に開発スピードが向上します。
と色々書きましたが、関数化は覚えておいて損はないので覚えておきましょう。
最後までご覧いただきありがとうございます。
・こちらの書籍を参考にVB.Net勉強しています。