Javaで配列の合計・平均を求める方法(forループ)
ループが終わると、途中まで数えた分が消えている
1 週間の気温から、真夏日 (30 度以上) が何日あったかを数えるとします。素直に書くと、こうなりがちです。
Java
for (int i = 0; i < temps.length; i++) {
int count = 0;
if (temps[i] >= 30) {
count++;
}
}動かしても、結果は 0 か 1 にしかなりません。int count = 0; がループの 中 にあるからです。1 周まわるたびに count は作り直され、0 に戻ります。前の周で数えた分は、次の周が始まった時点で消えています。
数えた結果を最後まで残したいなら、箱はループの外に置く必要があります。
答えを入れる箱を、ループの外に用意する
正しい形はこうです。
Java
int count = 0;
for (int i = 0; i < temps.length; i++) {
if (temps[i] >= 30) {
count++;
}
}
System.out.println(count);やっていることは 3 つです。ループの前に箱を用意し、ループの中で中身を書き換え、ループが終わった時点の中身を答えとして使う。配列を 1 周なめて 1 つの答えを作るこの形を 累積 と呼びます。
大事なのは、箱の中身を 前の周から引き継いで更新している ことです。count++ は「いまの値に 1 足す」という意味で、それまでの結果を土台にしています。ここを count = 1; と書いてしまうと毎周同じ値で上書きされ、最後の 1 周の結果しか残りません。配列を回したのに答えがいつも同じ、という症状が出たら、まずここを疑ってください。
数える代わりに足す、条件に合うものだけ拾う。ループの中の 1 行を差し替えるだけで、集計はひととおり書けるようになります。
空の配列では、初期値がそのまま答えになる
要素が 0 個の配列を渡すと、ループは 1 周も回りません。箱の中身は、用意したときの値のまま返ることになります。
つまり、最初に何を入れておくかが、空の配列に対する答えそのもの です。真夏日を数えるなら 0 日、これは int count = 0; の 0 がそのまま返ります。特別な分岐を書かなくても答えが合うのは、初期値をたまたま正しく選んでいたからです。
逆に言えば、初期値は「何もなかったときの答え」として選ぶものです。0 から始めるのが自然かどうかを、集計の種類ごとに考える癖をつけてください。ここを何となく 0 にしておくと、後で答えの合わない集計を書くことになります。
途中の値が見たくなったら、ループの中に
System.out.println(i + " " + count);を 1 行入れてみましょう。1 周ごとの箱の中身が並ぶので、引き継げているかどうかが一目で分かります。
やってみよう
今回は、配列の中身をすべて足した合計を返すメソッドを書きます。上の例と違うのは、ループの中で何をするかだけです。
空の配列を渡したときは 0 が返ります。ただしそれは、空の配列用の分岐を足したからではなく、初期値をそう選んだからです。その違いを意識して書いてみてください。書けたら、負の数だけが入った配列でも正しい答えになるか確かめておきましょう。
要件
- クラス名は
Solution、メソッド名はarraySum、引数はint[] arrひとつにすること - メソッドの戻り値の型は
intで、配列の中身の合計を返すこと - 空配列
{}のときは0を返すこと (ループに入らないケースに対応)
入出力例
arraySum([1,2,3]) → 6
arraySum([]) → 0
arraySum([-5,5]) → 0
arraySum([10]) → 10
arraySum([3,1,4,1,5,9,2,6]) → 31