https://www.acmicpc.net/problem/2755
2755번: 이번학기 평점은 몇점?
첫째 줄에, 백준이가 이번 학기에 들은 과목 수가 주어진다. 둘째 줄부터 N개의 줄에 각 과목의 과목명, 학점, 성적이 주어진다. 과목명은 알파벳 소문자와 숫자, 그리고 밑줄 (_)로만 이루어져 있으며, 최대 100글자이고, 학점은 1보다 크거나 같고, 3보다 작거나 같은 자연수이다. 성적은 문제에 설명한 13가지 중 하나이다.
www.acmicpc.net
#C++ 소수점 반올림 안됨. fixed가 고장났을때
#1. 다음의 결과를 예측해 보자.
cout<<fixed<<setprecision(2)<<3.27555<<"\n";
cout<<fixed<<setprecision(2)<<3.275<<"\n";
cout<<fixed<<setprecision(2)<<3.279<<"\n";
#2. 정상적으로 답을 낸다면 3.28 이 나와야 된다. 그러나 결과는 아니다.
결과:
3.28
3.27
3.28
#3. 왜그런걸까? 부동소수점 오차.
QnA에서 다음과 같은 답을 얻었다.
해당 문제에서 예제의 경우 3.275가 답이 되어 아래 코드의 첫 번째 줄과 같이 출력하게 되면, 반올림 처리가 되는데도 불구하고 3.27로 나오기도 합니다 .
실수의 연산이기에 디버깅을 위해 찍어봐도 3.27500000으로 나오지만 실제로는 3.274999999999......의 값을 갖게 되어 2번째 줄과같이 처리를 해 주어야 하는데 이것이 의도된 것인지 궁금합니다 .
0.000000000001
1
printf("%.2f\n", ans); // 틀렸습니다
2
printf("%.2f\n", ans + 0.000000000001); // 정답
부동소수점수의 표현 방법에 대해 알아보시면 좋을 듯 합니다.
불안정성을 의도했다기보다는, 표현 범위를 확장하기 위해 오차가 발생하는 것을 감안했다고 봐야 합니다.
#4. 해결책은
ans += 0.000000000001;
와 같이 처리를 해 주어야 한다.
//2755
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
// cout<<fixed<<setprecision(2)<<3.27555<<"\n";
// cout<<fixed<<setprecision(2)<<3.275<<"\n";
// cout<<fixed<<setprecision(2)<<3.279<<"\n";
//입력만 잘 해
double scoreSum = 0;
int haczuamSum = 0;
int n; cin>>n;
for(int i = 1 ;i <=n; i++){
string name; int haczuam; string score;
cin>>name>>haczuam>>score;
haczuamSum+=haczuam;
if( score =="A+" ){ scoreSum += 4.3*(double)haczuam; }
else if( score == "A0"){ scoreSum += 4.0*(double)haczuam;}
else if( score == "A-"){ scoreSum += 3.7*(double)haczuam;}
else if( score == "B+"){ scoreSum += 3.3*(double)haczuam;}
else if( score == "B0"){ scoreSum += 3.0*(double)haczuam;}
else if( score == "B-"){ scoreSum += 2.7*(double)haczuam;}
else if( score == "C+"){ scoreSum += 2.3*(double)haczuam;}
else if( score == "C0"){ scoreSum += 2.0*(double)haczuam;}
else if( score == "C-"){ scoreSum += 1.7*(double)haczuam;}
else if( score == "D+"){ scoreSum += 1.3*(double)haczuam;}
else if( score == "D0"){ scoreSum += 1.0*(double)haczuam;}
else if( score == "D-"){ scoreSum += 0.7*(double)haczuam;}
else{ scoreSum += 0.0;}
}
double ans = (scoreSum)/(double)haczuamSum ;
ans += 0.000000000001;
cout<<fixed<<setprecision(2)<<ans<<"\n";
return 0;
}
/*
FB1.
// cout<<fixed<<setprecision(2)<<3.27555<<"\n";
// cout<<fixed<<setprecision(2)<<3.275<<"\n";
// cout<<fixed<<setprecision(2)<<3.279<<"\n";
해당 문제에서 예제의 경우 3.275가 답이 되어 아래 코드의 첫 번째 줄과 같이 출력하게 되면, 반올림 처리가 되는데도 불구하고 3.27로 나오기도 합니다
실수의 연산이기에 디버깅을 위해 찍어봐도 3.27500000으로 나오지만 실제로는 3.274999999999......의 값을 갖게 되어 2번째 줄과같이 처리를 해 주어야 하는데 이것이 의도된 것인지 궁금합니다
0.000000000001
1
printf("%.2f\n", ans); // 틀렸습니다
2
printf("%.2f\n", ans + 0.000000000001); // 정답
djm03178 2달 전좋아요
부동소수점수의 표현 방법에 대해 알아보시면 좋을 듯 합니다.
불안정성을 의도했다기보다는, 표현 범위를 확장하기 위해 오차가 발생하는 것을 감안했다고 봐야 합니다.
*/
플라즈마 IT 블로그 - 코딩 공부 정리, IT 정보 공유
https://plasmacodeing.tistory.com/
조금이라도 도움이 되었다면 공감 및 댓글 주세요~~
'알고리즘 > 백준[BOJ] 오답노트' 카테고리의 다른 글
C++ fill 이용한 배열 초기화 1차원 배열 2차원 배열 (0) | 2020.01.20 |
---|---|
C++ 배열 인덱스 1부터 사용 하기 - 백준 알고리즘 오답노트 2011 (0) | 2019.05.07 |
구름IDE 디버깅 하는 방법 - 백준 알고리즘 오답노트 1913 (0) | 2019.05.07 |
알고리즘 고수의 코드를 보다. - 백준 알고리즘 오답노트 5073 (0) | 2019.05.07 |
다이나믹 프로그래밍 오버플로어 - 백준 알고리즘 오답노트 1012 (0) | 2019.05.07 |