문제내용
해석
두 정수를 A, B로 입력받고 A/B값을 출력합니다.
cout << A/B만 하면 된다고 생각하지만 그렇게 하면 문제의 절대오차, 상대오차라는 조건을 무시하게 되고, 코드도 통과되지 않습니다.
그렇다면 절대오차나 상대오차를 어떻게 처리해줘야 할까 생각하게 됩니다.
오차의 개념은 다음과 같습니다. https://whitecode2718.tistory.com/42
" 참값 = 근삿값 + 오차 "에서 우리가 출력하는 건 근삿값이 됩니다. 즉, 1/3을 출력하면 0.333333... 의 참값을 오차를 감안하고 근삿값으로 0.333이나 0.333333으로 출력한다는 뜻입니다.
즉, "오차"가 10-9라는 이야기는 근삿값 + 0.000000001 = 참값으로 인정한다는 말이고, 이 오차 이내는 당연히 10-10이 아니라 10-8, 10-7을 포함합니다. 쉽게 생각하면 자릿수 오차를 9자리까지 허용한다는 말입니다.
예를 들면 1/3의 참값은 0.33333333...이고 근삿값을 0.333333333이면 (참값 - 근삿값 =) 오차의 오차는 0.0000000003...이고 이 오차는 10-9 보다작기에 문제의 조건을 만족합니다.
하지만 근삿값이 0.333이라면 오차는 0.000333...으로 허용 오차인 10-9보다 훨씬 크다는 것을 알 수 있습니다.
이를 통해 우리가 출력하게 될 근삿값이 9 자릿수 이상이라면 위의 10-9 오차 조건을 만족할 수 있을 거라고 생각할 수 있습니다.
여기서 오차라는 개념을 무시하고 자릿수를 그냥 9자리로 맞춰도 답은 나오지만 추천하지 않습니다.
풀이
입력은 기본적으로 변수에 저장하는 방식으로 이용하고 연산 또한 ' / ' 연산자를 그대로 쓰면 쉽게 값을 구할 수 있습니다. 이때 주의 할 건 출력하는 근삿값을 위의 오차개념에 맞추어 설정해주어야 합니다.
해석을 보면 자릿수를 9이상으로 만들면 오차조건을 만족할 수 있으므로 출력을 9자리로 맞춰주면 됩니다.
printf( )함수로 출력하고자 한다면 %. f로 출력 지정을 하면 되지만 저는 <iostream> 헤더파일의 파생 클래스인 <ostream> 헤더파일을 사용해 출력할 것이기 때문에 precision( ) 포맷함수를 사용할 것입니다.
포맷 함수: https://whitecode2718.tistory.com/25
#include<iostream>
using namespace std;
int main(){
double x,y;
cin >> x >> y;
cout.precision(9);
cout << fixed;
cout << x/y;
cout.unsetf(ios::fixed);
}
fixed는 endl처럼 매개 변수가 없는 조작자이고, 실수 필드를 고정 소수점 방식으로 출력하기 위한 cout의 출력모드를 바꿔줍니다.
코드를 순서대로 읽으면 x, y를 double로 입력받고 (자릿수가 float가 아니라 더 길 수도 있기 때문에) cout의 출력 모드를 고정 소수점 즉, 소수점을 정하는 방식으로 출력하게 만들고 x/y를 소수점 9자리까지 출력한 후 출력모드 fixed를 해제합니다.
물론 cout의 모드를 해제하지 않아도 다음 출력을 똑같이 fixed로 할 거라면 해제하지 않아도 됩니다. 문제는 소수점만 출력하면 되므로 fixed 출력 모드를 해제하지 않아도 됩니다.
precision(9)를 실행시키기 위해 cout를 fixed의 모드로 바꾼 것이기 fixed의 모드로 바꾸지 않고 출력한다면 당연히 오류가 발생합니다.
#include<iostream>
using namespace std;
int main(){
double x,y;
cin >> x >> y;
cout.precision(9);
cout << fixed;
cout << x/y;
}
정리
간단한 형식의 문제지만 이 문제를 통해 절대오차와 상대오차의 개념과 오차 조건이 주어졌을 때 어떻게 출력해야 이를 만족할 수 있는지 학습할 수 있습니다.
이런 출력을 위해 출력 모드를 바꾼 후 포맷 함수를 사용하고, 출력모드를 해제하는 연습도 할 수 있으며 C++의 <iostream>으로 <ostream>헤더파일에 선언된 precision( )를 사용할 수 있는 이유인 파생 클래스 개념 또한 상기시킬 수 있었습니다.
마지막으로 이 문제를 풀 때 오차를 제대로 이해하지 않고 10^-9만 보고 9자리라고 맞춘다면 precision(8)은 답이 틀리고 precision(10)은 통과하는 이유를 이해하지 못할 겁니다.
'프로그래밍 > 코딩 테스트 연습' 카테고리의 다른 글
[백준] 10926번 : ??! (1단계) (C++) (0) | 2024.01.04 |
---|---|
[백준] 10869번 : 사칙연산 (1단계) (C++) (0) | 2024.01.04 |
[백준] 10998번 : A * B (1단계) (C++) (1) | 2024.01.03 |
[백준] 1001번 : A - B (1단계) (C++) (0) | 2024.01.03 |
[백준] 1000번 : A + B (1단계) (C++) (1) | 2024.01.02 |