未来エンジニア養成所Blog

月単価180万以上のプログラミング講師がプログラミングを皆に楽しんでもらうための情報をお届けします。

【Java】基本構文に関する問題1-21

title


問題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公式アカウント

仕事が辛くてたまらない人生が、仕事が楽しくてたまらない人生に変わります。
【登録いただいた人全員に、無料キャリア相談プレゼント中!】


LineOfficial

友だち追加