問題1-21
100人分のテストの点数を格納しているint配列型の変数pointsがあります。
この試験の平均点の算出と、ヒストグラムを作成してください。
ヒストグラムは、階級ごとに個数を集計し、グラフ化したものです。
階級は、0点台(0〜9点)、10点台(10〜19点)、・・・90点台(90〜100点)とします。
(100点満点の人を90点台に含めているのがポイントです)
【実行結果】
平均点:60.3 ヒストグラム 0点台 * 10点台 ** 20点台 ****** 30点台 ** 40点台 ************** 50点台 **************** 60点台 **************************** 70点台 ***************** 80点台 ********** 90点台 ****
【ForArrayNormalPractice.java】
public class ForArrayNormalPractice { public static void main(String[] args) { // 100人分のテストの点数を格納した配列変数points int[] points = { 69, 40, 88, 68, 13, 62, 45, 43, 28, 69, 54, 77, 81, 34, 41, 78, 59, 21, 45, 64, 55, 18, 63, 80, 64, 26, 52, 44, 61, 50, 44, 82, 56, 74, 67, 98, 58, 84, 77, 70, 60, 77, 64, 89, 59, 74, 21, 66, 85, 68, 90, 48, 64, 80, 63, 47, 70, 79, 51, 66, 23, 84, 57, 57, 76, 60, 100, 66, 79, 61, 47, 66, 76, 45, 90, 69, 72, 51, 86, 64, 57, 51, 42, 60, 71, 69, 7, 62, 77, 61, 43, 50, 68, 30, 78, 58, 40, 62, 70, 22 }; // ここからコーディングしてください } }
解答例
【ForArrayNormalPractice.java】
public class ForArrayNormalPractice { public static void main(String[] args) { // 100人分のテストの点数を格納した配列変数points int[] points = { 69, 40, 88, 68, 13, 62, 45, 43, 28, 69, 54, 77, 81, 34, 41, 78, 59, 21, 45, 64, 55, 18, 63, 80, 64, 26, 52, 44, 61, 50, 44, 82, 56, 74, 67, 98, 58, 84, 77, 70, 60, 77, 64, 89, 59, 74, 21, 66, 85, 68, 90, 48, 64, 80, 63, 47, 70, 79, 51, 66, 23, 84, 57, 57, 76, 60, 100, 66, 79, 61, 47, 66, 76, 45, 90, 69, 72, 51, 86, 64, 57, 51, 42, 60, 71, 69, 7, 62, 77, 61, 43, 50, 68, 30, 78, 58, 40, 62, 70, 22 }; // 合計を集計するための変数 int sum = 0; // テスト結果数分のループ for(int i = 0; i < points.length; i++) { // 点数を加算していく sum += points[i]; } // 平均点の出力 System.out.println("平均点:" + ((double)sum / points.length)); System.out.println("ヒストグラム"); // 階級毎のループ for(int i = 0; i < 10; i++) { // 0点台の表示を調整 if(i == 0) { System.out.print(" 0点台"); } else { System.out.print((i * 10) + "点台"); } // 全員分のテストの点数を走査 for(int j = 0; j < points.length; j++) { // 対象者の場合はアスタリスクを出力 if(points[j] >= (i * 10) && points[j] < ((i + 1) * 10)) { System.out.print("*"); } // 100点の特別な処置 if(i == 9 && points[j] == 100) { System.out.print("*"); } } System.out.println(); } } }
【ForArrayNormalPractice2.java】
public class ForArrayNormalPractice2 { public static void main(String[] args) { // 100人分のテストの点数を格納した配列変数points int[] points = { 69, 40, 88, 68, 13, 62, 45, 43, 28, 69, 54, 77, 81, 34, 41, 78, 59, 21, 45, 64, 55, 18, 63, 80, 64, 26, 52, 44, 61, 50, 44, 82, 56, 74, 67, 98, 58, 84, 77, 70, 60, 77, 64, 89, 59, 74, 21, 66, 85, 68, 90, 48, 64, 80, 63, 47, 70, 79, 51, 66, 23, 84, 57, 57, 76, 60, 100, 66, 79, 61, 47, 66, 76, 45, 90, 69, 72, 51, 86, 64, 57, 51, 42, 60, 71, 69, 7, 62, 77, 61, 43, 50, 68, 30, 78, 58, 40, 62, 70, 22 }; // 階級を集計するための配列変数 int[] level = new int[10]; // 合計を集計するための変数 int sum = 0; // テスト結果数分のループ for(int i = 0; i < points.length; i++) { // 点数を加算していく sum += points[i]; // 階級ごとに数え上げる // 100点のみ特別に扱う if(points[i] == 100) { level[9]++; } else { level[points[i] / 10]++; } } // 平均点の出力 System.out.println("平均点:" + ((double) sum / points.length)); System.out.println("ヒストグラム"); // 階級毎のループ for(int i = 0; i < level.length; i++) { // 0点台の表示を調整 if(i == 0) { System.out.print(" 0点台"); } else { System.out.print((i * 10) + "点台"); } // 階級の人数分アスタリスクを出力 for(int j = 0; j < level[i]; j++) { System.out.print("*"); } System.out.println(); } } }
解説
今回の問題は非常に自由度が高く、解答例を2パターン載せました。
1つ目の解答例はオーソドックス、2つ目の解答例はやや高度な発想になっています。
まずは1つ目の解答例のコードについて解説します。
int配列型のデータを調査するので、もちろんfor文を使って走査します。
そして、まずはじめに平均値を算出して出力します。
平均値を算出するためには、配列の各要素を合計してから個数で割らないといけません。
よって、一回目のfor文は各要素の合計値を算出するために使用します。
// 合計を集計するための変数 int sum = 0; // テスト結果数分のループ for(int i = 0; i < points.length; i++) { // 点数を加算していく sum += points[i]; } // 平均点の出力 System.out.println("平均点:" + ((double)sum / points.length));
合計値格納用の変数sumを宣言し、そこに配列の各要素の値を加算していきます。
最後にその合計値を配列の要素数で割るわけですが、int型の値をint型の値で割ってしまうと演算結果もint型になってしまうので正しい平均点が算出できません。
そのために、変数sumをdouble型でキャストしているのがポイントになります。
はじめから変数sumをdouble型で宣言するのもOKです。
次に、ヒストグラムを表示するためのfor文を記述します。
ここで、for文をネストするのが最大のポイントです。
最初のfor文は0点台、10点台、・・・・、90点台という階級に関するfor文です。
もしかしたら、階級のループを使わずに0点台から90点台までの10パターンをすべてそのまま記述した人もいるかもしれません。
結果は正しいかも知れませんが、「規則性のある繰り返し」はそのまま記述してはいけません。
// 対象者の場合はアスタリスクを出力 if(points[j] >= (i * 10) && points[j] < ((i + 1) * 10)) { System.out.print("*"); }
外側のループ変数iの値をうまく使って、階級毎の点数の範囲を作っています。
ちょっと難しく見えますが、紙とペンを使って数値の範囲を次のように書き並べれば、この規則性に気が付くでしょう。
0点台は0〜9 10点台は10〜19 20点台は20〜29 30点台は30〜39 ・・・・
ただし、問題文にもありましたが、100点満点の人だけは特別に90点台に含めないといけないので、この規則性から外れています。
ここはうまく微調整を行っています。
次に2つ目の解答例のコードを解説します。
1つ目の解答例と大きく異なるのは、平均値を算出するための最初のfor文で各階級の数え上げも同時に行っている点です。
int配列型変数levelを宣言し、要素数10で配列オブジェクトを生成しています。
階級を数え上げるためのlevel配列の要素数は10ですので、インデックス番号としては0から9まで存在します。
それをインデックス番号0なら「0点台」、インデックス番号1なら「10点台」・・・・というように、インデックス番号と階級(0点台から90点台)を関連づけているのです。
階級の数え上げに配列を使わず、10個の変数を宣言した人もいるかもしれませんが、今回の方法が簡潔で良いと考えます。
あとは点数を10で割った値が階級のインデックス番号になります。
つまり、32点なら10で割ると3になるのでそのまま配列のインデックス番号として使用できます。
ただし、100点のみ特別で、90点台として数えるという指示がありました。
よって、if文を使って100点は90点台として数えています。
あとは階級level配列変数を走査し、各階級の数値分アスタリスクを出力します。
1つ目の解答例でもそうでしたが、0点台だけ表示をそろえるためにif文を使ってスペースを埋めて調整しています。
参考図書
LINE公式アカウント
仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】