알고리즘/백준[BOJ] 오답노트

C++ 소수점 반올림 안됨. fixed가 고장났을때 - 백준 알고리즘 오답노트 2755

플라즈밍 2019. 5. 7. 10:30
반응형

 

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/

 

조금이라도 도움이 되었다면 공감 및 댓글 주세요~~

 

 

 

반응형