프로그래밍/PS
[C++] 백준 6986번: 절사평균
유태정
2020. 12. 22. 17:36
반응형
풀이과정
1. 수열을 벡터로 입력받고, STL sort 함수로 정렬한다.
2. 절사평균은 \(\frac{\sum_{i=K}^{N-K-1}{arr[i]}}{N-2K}\)의 값을 출력한다.
3. 보정평균은 \(\frac{arr[K]\times{K}+arr[N-K-1]\times{K}+\sum_{i=K}^{N-K-1}{arr[i]}}{N}\)의 값을 출력한다.
주의사항
1. 벡터의 형식은 double이다.
2. 출력할 때, 다음과 같이 해야 소숫점 아래 3번째 자리에서 반올림을 하여 표시된다. 뿐만 아니라 소숫점 아래 2번째 자리까지의 표시가 고정된다.
cout.precision(2);
cout << fixed;
3. 실수 데이터 타입에서의 오차
https://www.youtube.com/watch?v=T9l891a0f3o
위 영상에서 처럼, 소숫점을 메모리에 저장할 때 대부분의 수에서 오차가 발생하게 된다. 소숫점 아래가 \(2^{-1}, 2^{-2}, ...\)과 같은 수가 아니면 무한소수가 되기 때문에 무조건 오차가 발생할 수 밖에 없다. 따라서 출력할 때, 반올림에서 문제가 생길 수 있는데, 예를 들면 다음과 같은 경우다.
4.45로 저장되어야 할 수가 4.44999999999999로 저장된 경우. 이 경우에는 소숫점 아래 셋째 자리에서 반올림하면 4.5가 되어야 할 수가 4.4가 돼 버린다. 따라서 적당한 수를 더해줌으로써 이를 해결해야되는데, 나는 1e-13 정도의 수를 더해줌으로써 해결했다. 다만 1e-15부터는 의미가 없게되니 주의해야한다. 1e-15는 0이 된다.
코드
#include <bits/stdc++.h>
using namespace std;
#define TC(T) int T; cin >> T; while(T--)
#define FAST_IO cin.tie(NULL); ios::sync_with_stdio(false);
#define FOR(i, N) for(int i = 0; i < N; ++i)
#define INF 987654321
#define ERR 1e-13
#define EL "\n"
int main() {
#ifdef DEBUG
freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
FAST_IO;
int N, K;
cin >> N >> K;
vector<double> arr(N);
FOR(i, N)
cin >> arr[i];
sort(arr.begin(), arr.end());
double trimmed = 0.0;
for (int i = K; i < N - K; ++i)
trimmed += arr[i];
trimmed /= (N - 2 * K);
cout.precision(2);
cout << fixed;
cout << trimmed + ERR << EL;
double adjusted = arr[K] * K + arr[N - K - 1] * K;
for (int i = K; i < N - K; ++i)
adjusted += arr[i];
adjusted /= N;
cout.precision(2);
cout << fixed;
cout << adjusted + ERR << EL;
return 0;
}
반응형