{ }codelper
平均P0225

クラス平均と学年平均

ある学年にクラスが m 個ある。
一行目に m が与えられる。
続く m 行に、クラスごとにそのクラスの生徒数 k と k 人の点数が空白で区切って一行に与えられる。
クラスごとに、そのクラスの平均点を入力の順に一行ずつ出力せよ。
最後の行には学年平均を出力せよ。
学年平均は、学年のすべての生徒の点数を足した値を学年全体の生徒数で割った値である。
平均はすべて小数第三位で四捨五入し、小数点以下ちょうど二桁で書く(85 → 85.00)。
四捨五入で迷わないように、出力するすべての平均は 100 倍したときの小数部分が 0.4 以下か 0.6 以上になるように与えられる。

入力
1 ≤ m ≤ 100、1 ≤ k ≤ 100、0 ≤ 点数 ≤ 100(整数)
出力
m 行のクラス平均、最後の行に学年平均(すべて小数第二位まで)
例 1 · stdin
2
3 90 80 70
1 100
stdout
80.00
100.00
85.00
例 2 · stdin
2
3 0 0 1
2 100 100
stdout
0.33
100.00
40.20
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

いちばん大きな落とし穴は平均の平均です。
クラス平均を足してクラス数で割ると、クラスの人数が違うとき学年平均と違ってしまいます。
3 人で平均 80 のクラスと 1 人で平均 100 のクラスをもう一度平均すると 90 ですが、生徒 4 人の平均は 340 ÷ 4 = 85 です。
そこでクラスごとの点数の合計と生徒数を別々に集めておき、最後に割ります。
クラスの合計はクラスごとに 0 からやり直します。
二つ目の落とし穴は整数の割り算です。
C・C++・Java・C# の s / k は int 同士なので商だけが残ります。
(double)s / k(C++ は static_cast<double>(s) / k)のように先に変えてから割ります。
double avg = s / k; や (double)(s / k) は小数がもう捨てられたあとです。
Python 3・JS・TS・Craykon の / はいつも小数まで割ります。
小数二桁は Python f"{x:.2f}"、JS・TS x.toFixed(2)、C printf("%.2f")、Java String.format(Locale.ROOT, "%.2f", x)、C# x.ToString("F2", CultureInfo.InvariantCulture)、Craykon 文字.桁そろえ(x, 2) です。
C++ は必ず std::fixed もいっしょに書きます。
std::setprecision(2) だけだと小数の桁ではなく有効数字二桁なので、33.33 が 33 と出ます。
一行に生徒数と点数がいっしょに来るので、Python は k, *scores = map(int, line.split())、JS・TS は const [k, ...scores] = … で分けて受け取ると便利です。

Pythonmain.py · 11 行
m = int(input())out = []total = count = 0for _ in range(m):    k, *scores = map(int, input().split())    s = sum(scores)    out.append(f"{s / k:.2f}")    total += s          # 학년 평균은 반 평균이 아니라 점수 합과 학생 수를 모아서 구한다    count += kout.append(f"{total / count:.2f}")print("\n".join(out))
JavaScriptmain.js · 15 行
const lines = require("fs").readFileSync(0, "utf8").split("\n");const m = Number(lines[0]);const out = [];let total = 0;let count = 0;for (let i = 1; i <= m; i++) {  const [k, ...scores] = lines[i].trim().split(/\s+/).map(Number);  let s = 0;  for (const x of scores) s += x;  out.push((s / k).toFixed(2));  total += s; // 학년 평균은 점수 합과 학생 수를 모아서 구한다  count += k;}out.push((total / count).toFixed(2));console.log(out.join("\n"));
TypeScriptmain.ts · 16 行
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const m: number = Number(lines[0]);const out: string[] = [];let total = 0;let count = 0;for (let i = 1; i <= m; i++) {  const [k, ...scores]: number[] = lines[i].trim().split(/\s+/).map(Number);  let s = 0;  for (const x of scores) s += x;  out.push((s / k).toFixed(2));  total += s; // 학년 평균은 점수 합과 학생 수를 모아서 구한다  count += k;}out.push((total / count).toFixed(2));console.log(out.join("\n"));
JavaMain.java · 26 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Locale;import java.util.StringTokenizer; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int m = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        int total = 0, count = 0;        for (int i = 0; i < m; i++) {            StringTokenizer st = new StringTokenizer(in.readLine());            int k = Integer.parseInt(st.nextToken());            int s = 0;            for (int j = 0; j < k; j++) s += Integer.parseInt(st.nextToken());            // int끼리 나누면 몫만 남으니 한쪽을 double로            out.append(String.format(Locale.ROOT, "%.2f", (double) s / k)).append('\n');            total += s;            count += k;        }        out.append(String.format(Locale.ROOT, "%.2f", (double) total / count)).append('\n');        System.out.print(out);    }}
C#Main.cs · 26 行
using System;using System.Globalization;using System.Linq;using System.Text; class Program{    static void Main()    {        int m = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        int total = 0, count = 0;        for (int i = 0; i < m; i++)        {            int[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray();            int k = p[0];            int s = p.Skip(1).Sum();            // int끼리 나누면 몫만 남으니 한쪽을 double로            sb.Append(((double)s / k).ToString("F2", CultureInfo.InvariantCulture)).Append('\n');            total += s;            count += k;        }        sb.Append(((double)total / count).ToString("F2", CultureInfo.InvariantCulture)).Append('\n');        Console.Write(sb);    }}
C++main.cpp · 24 行
#include <iomanip>#include <iostream> int main() {    std::ios::sync_with_stdio(false);    int m;    std::cin >> m;    int total = 0, count = 0;    std::cout << std::fixed << std::setprecision(2);    for (int i = 0; i < m; i++) {        int k;        std::cin >> k;        int s = 0;        for (int j = 0; j < k; j++) {            int x;            std::cin >> x;            s += x;        }        std::cout << static_cast<double>(s) / k << "\n";        total += s;        count += k;    }    std::cout << static_cast<double>(total) / count << "\n";}
Cmain.c · 20 行
#include <stdio.h> int main(void) {    int m, k, x;    int total = 0, count = 0;    scanf("%d", &m);    for (int i = 0; i < m; i++) {        scanf("%d", &k);        int s = 0;        for (int j = 0; j < k; j++) {            scanf("%d", &x);            s += x;        }        printf("%.2f\n", (double)s / k); /* (double)로 바꾼 뒤에 나눈다 */        total += s;        count += k;    }    printf("%.2f\n", (double)total / count);    return 0;}
Craykonmain.cray · 17 行
m = コンソール.行読み().数に();total = 0;count = 0;繰り返す (i = 0; i < m; i++){    p = コンソール.数読み();    k = p[0];    s = 0;    繰り返す (j = 1; j <= k; j++)    {        s += p[j];    }    コンソール.書く(文字.桁そろえ(s / k, 2));    total += s; // 학년 평균은 점수 합과 학생 수를 모아서 구한다    count += k;}コンソール.書く(文字.桁そろえ(total / count, 2));