{ }codelper
float divisionsquare rootP0168

Mean and standard deviation of sensor readings

A factory collected the values its sensors measured over the same period. For each sensor we find the mean and standard deviation of its values to see how much they wobbled. The first line gives the number of sensors s. Each of the next s lines gives, for one sensor, the count n and n integer values, separated by spaces. The mean m is the sum of the values divided by n, as a real number. The standard deviation is found by squaring (value - m) for each value, adding them all, dividing that sum by n and taking the square root (divide by n, not n - 1). For each sensor, in input order, print one line with the mean and the standard deviation rounded to three decimal places, separated by one space. Write three decimals even when the value is a whole number (80 → 80.000). So that rounding never sits on a boundary, no input is given in which the mean or the standard deviation times 1000 has a fractional part from 0.49 to 0.51.

Input
1 ≤ s ≤ 20, 1 ≤ n ≤ 1,000, 0 ≤ value ≤ 1,000,000,000, no input where the mean or standard deviation × 1000 has a fractional part of 0.49 to 0.51
Output
One line per sensor: the mean and standard deviation (three decimal places)
Example 1 · stdin
4
5 70 80 90 85 75
1 1000000000
4 999999999 1000000000 1000000001 1000000000
3 1 2 2
stdout
80.000 7.071
1000000000.000 0.000
1000000000.000 0.707
1.667 0.471
main.py
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

The first trap is in the division.
Python 3's /, JS/TS / and Craykon's / are always real division, so sum / n gives 1.667 directly.
In C, C++, Java and C#, dividing two integers is integer division, so 5 / 3 is 1, and putting it into a double still gives 1.0.
So turn one side into a real number before dividing, as in (double)sum / n (C++ static_cast<double>(sum) / n).
The second trap is the size of the sum.
The sum of 1,000 values of 10^9 is 10^12, beyond int (about 2.1 billion) in C, C++, Java and C#, so collect it in long long / long.
Python integers and the doubles of JS, TS and Craykon are exact at this size.
The third trap is the formula.
If you get the variance in one pass as "mean of squares - square of mean", then when the values are near 10^9 and the wobble is small you subtract two reals of about 10^18.
A double has about 16 significant digits, so the difference (say 0.5) is buried under an error of hundreds, and it can even come out negative and make the square root NaN.
All eight languages use the same double, so all of them break the same way.
The safe way is two passes: find the mean first, then add up the squares of (value - mean).
Square root is Python math.sqrt, JS/TS Math.sqrt, Java Math.sqrt, C# Math.Sqrt, C sqrt (<math.h>, -lm with gcc), C++ std::sqrt (<cmath>), Craykon Mathf.Sqrt.
Three decimals are Python f"{x:.3f}", JS/TS toFixed(3), Java String.format("%.3f"), C# ToString("F3"), C/C++ printf("%.3f"), Craykon Str.Fixed(x, 3).
Java String.format and C# ToString follow the computer's locale and may print a comma as the decimal point, so the solutions pass Locale.ROOT (Java) and CultureInfo.InvariantCulture (C#).

Pythonmain.py · 9 lines
import math s = int(input())for _ in range(s):    n, *xs = map(int, input().split())    mean = sum(xs) / n  # Python 3의 /는 늘 실수 나눗셈이다    # 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다    var = sum((x - mean) ** 2 for x in xs) / n    print(f"{mean:.3f} {math.sqrt(var):.3f}")
JavaScriptmain.js · 12 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const s = Number(lines[0]);const out = [];for (let i = 1; i <= s; i++) {  const [n, ...xs] = lines[i].trim().split(/\s+/).map(Number);  // JS의 수는 모두 double이라 /는 늘 실수 나눗셈이다(합 10^12도 2^53 안이라 정확하다)  const mean = xs.reduce((a, b) => a + b, 0) / n;  // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다  const variance = xs.reduce((acc, x) => acc + (x - mean) ** 2, 0) / n;  out.push(`${mean.toFixed(3)} ${Math.sqrt(variance).toFixed(3)}`);}console.log(out.join("\n"));
TypeScriptmain.ts · 13 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const s = Number(lines[0]);const out: string[] = [];for (let i = 1; i <= s; i++) {  const [n, ...xs] = lines[i].trim().split(/\s+/).map(Number);  // JS의 수는 모두 double이라 /는 늘 실수 나눗셈이다(합 10^12도 2^53 안이라 정확하다)  const mean = xs.reduce((a, b) => a + b, 0) / n;  // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다  const variance = xs.reduce((acc, x) => acc + (x - mean) ** 2, 0) / n;  out.push(`${mean.toFixed(3)} ${Math.sqrt(variance).toFixed(3)}`);}console.log(out.join("\n"));
JavaMain.java · 27 lines
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.Locale; public class Main {    public static void main(String[] args) throws Exception {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        int s = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int k = 0; k < s; k++) {            String[] p = in.readLine().trim().split("\\s+");            int n = Integer.parseInt(p[0]);            long[] xs = new long[n];            long sum = 0; // 10^9 × 1,000 = 10^12: int로는 넘친다            for (int i = 0; i < n; i++) {                xs[i] = Long.parseLong(p[i + 1]);                sum += xs[i];            }            double mean = (double) sum / n; // long / int는 정수 나눗셈이라 한쪽을 double로 바꾼다            // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다            double sq = 0;            for (long x : xs) sq += (x - mean) * (x - mean);            out.append(String.format(Locale.ROOT, "%.3f %.3f", mean, Math.sqrt(sq / n))).append('\n');        }        System.out.print(out);    }}
C#Main.cs · 27 lines
using System;using System.Globalization;using System.Linq;using System.Text; class Program{    static void Main()    {        int s = int.Parse(Console.ReadLine());        var sb = new StringBuilder();        for (int k = 0; k < s; k++)        {            long[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToArray();            int n = (int)p[0];            long[] xs = p.Skip(1).ToArray();            long sum = xs.Sum(); // 10^9 × 1,000 = 10^12: int로는 넘친다            double mean = (double)sum / n; // long / int는 정수 나눗셈이라 한쪽을 double로 바꾼다            // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다            double sq = xs.Sum(x => (x - mean) * (x - mean));            double sd = Math.Sqrt(sq / n);            sb.Append(mean.ToString("F3", CultureInfo.InvariantCulture)).Append(' ')              .Append(sd.ToString("F3", CultureInfo.InvariantCulture)).Append('\n');        }        Console.Write(sb);    }}
C++main.cpp · 24 lines
#include <cmath>#include <cstdio>#include <iostream>#include <vector> int main() {    int s;    std::cin >> s;    for (int k = 0; k < s; k++) {        int n;        std::cin >> n;        std::vector<long long> xs(n);        long long sum = 0; // 10^9 × 1,000 = 10^12: int로는 넘친다        for (auto& x : xs) {            std::cin >> x;            sum += x;        }        double mean = static_cast<double>(sum) / n; // 한쪽을 double로 바꿔야 실수 나눗셈이 된다        // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다        double sq = 0;        for (long long x : xs) sq += (x - mean) * (x - mean);        std::printf("%.3f %.3f\n", mean, std::sqrt(sq / n));    }}
Cmain.c · 26 lines
#include <math.h>#include <stdio.h> int main(void) {    int s;    scanf("%d", &s);    static long long xs[1000];    for (int k = 0; k < s; k++) {        int n;        scanf("%d", &n);        long long sum = 0; /* 10^9 × 1,000 = 10^12: int(약 21억)로는 넘친다 */        for (int i = 0; i < n; i++) {            scanf("%lld", &xs[i]);            sum += xs[i];        }        double mean = (double)sum / n; /* 한쪽을 double로 바꿔야 실수 나눗셈이 된다 */        /* 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다 */        double sq = 0;        for (int i = 0; i < n; i++) {            double d = xs[i] - mean;            sq += d * d;        }        printf("%.3f %.3f\n", mean, sqrt(sq / n));    }    return 0;}
Craykonmain.cray · 20 lines
s = Console.ReadLine().ToNumber();for (k = 0; k < s; k++){    xs = Console.ReadNumbers();    n = xs[0]; // 맨 앞은 개수    sum = 0;    for (i = 1; i <= n; i++)    {        sum += xs[i];    }    // 크레이콘의 /는 늘 실수 나눗셈이다(정수 몫은 수학.몫)    mean = sum / n;    // 평균을 먼저 구하고 평균과의 차를 제곱해 더한다(두 번 훑기): 큰 수끼리 빼는 일이 없다    sq = 0;    for (i = 1; i <= n; i++)    {        sq += (xs[i] - mean) * (xs[i] - mean);    }    Console.WriteLine(Str.Fixed(mean, 3) + " " + Str.Fixed(Mathf.Sqrt(sq / n), 3));}