문제
절대오차와 상대오차
이 문제에서 "실제 정답과 출력값의 절대오차 또는 상대오차가 10⁻⁹ 이하면 정답" 이 정확히 어떻게 해결해야 한다는 것인지 몰랐기 때문에 고민해보아야 했습니다.
오차가 10⁻⁹(0.000000001)보다 작아야한다는 의미인건 대충 짐작했지만, 그렇다면 절대오차와 상대오차가 무엇을 의미하는 것인지 알아야 했습니다.
오차 (Error)
오차란 참값과 근삿값의 차이를 말합니다. 즉, 근삿값에서 참값을 뺀 값입니다.
절대오차 (Absolute Error)
절대오차는 참값에서 결과값을 뺀 수치의 "절댓값"을 말합니다.
수치적인 차이를 의미하기 때문에 측정된 값과 같은 단위를 사용합니다.
예를 들어 170cm(참값)가 되고싶은 어린이의 실제 키가 136cm(결과값)라면 절대오차는
170(cm) - 136(cm) = 34(cm) 가 됩니다.
상대오차 (Relative Error)
상대오차는 절대오차를 참값으로 나눈 값을 말합니다. 백분율오차(Percentage Error)라고도 합니다.
때문에 절대오차를 구해야 상대오차를 구할 수 있습니다.
예로 위의 예시에서 절대오차는 34cm이고, 참값인 170cm를 나누면
34(cm) / 170(cm) = 0.2 가 나옵니다.
0.2에 100을 곱해 백분율로 바꾼 20%가 상대오차가 됩니다.
오차가 10⁻⁹ 이하면 정답
절대오차
절대오차가 10⁻⁹보다 작으면 정답이라는 의미는, 실제 정답에 0.0000000010 이하의 값을 더하거나 빼도 정답으로 처리한다는 의미입니다.
예를 들어 실제 답이 1.1111111111 인데 내가 출력한 답이 1.1111111000이라면, 오차가 0.0000000111입니다.
즉, 오차가 10⁻⁹보다 0.0000000101만큼 크므로 정답으로 인정되지 않습니다.
다시 말하자면, 정확한 답을 연산했다 하더라고 최소한 소수점 아래 9번째 자리까지는 출력해야 정답으로 인정되는 오차범위 내에 들어간다는 의미입니다.
상대오차
상대오차는 절대오차와 다릅니다.
상대오차 10⁻¹까지 허용한다고 하면, 10⁻¹에 100을 곱한 10%의 오차까지 허용한다는 말입니다. 만약 10⁻²까지 허용한다고 하면, 1%의 오차까지 허용한다는 의미입니다.
즉 상대오차가 10⁻⁹보다 작으면 정답이라는 의미는, 0.0000001%의 오차까지 허용한다는 의미가 됩니다.
해결
즉 이 문제를 해결하려면,
1. 소수점 아래 9번째 이하까지 정밀한 연산이 되어야 합니다.
2. 연산한 값을 소수점 9번째 자리까지 출력해야 합니다.
부동소수점형
C++에서 실수는 부동소수점 방식으로 표시하는데, float과 double, long double 자료형을 이용할 수 있습니다.
float형은 유효숫자를 6자리까지 나타낼 수 있기 때문에 double형을 사용하는게 적당합니다.
float (단일정밀도 부동소수점) | double (두배정밀도 부동소수점) | |
크기 | 4바이트 (32비트) | 8바이트 (64비트) |
지수 부분 | 8비트 | 11비트 |
가수 부분 | 나머지 24비트 | 나머지 53비트 |
유효 숫자 | 6자리 | 15자리 |
자리수 고정
C++에서 cout을 통해 소수점 아래 9번째 자리까지 출력하려면, cout.precision()을 사용할 수 있습니다.
precision()은 정수를 포함한 전체 자리수를 n자리로 표현하는 것입니다.
정수 부분에 상관 없이 소수점 아래만 고정하려면, fixed를 precision() 이후에 사용하면 됩니다. precision()으로 넘긴 값 만큼 소수점 아래자리수가 고정됩니다.
fixed를 해제하려면, unsetf(ios::fixed)를 사용하면 됩니다.
코드
#include <iostream>
using namespace std;
int main(){
double a,b;
cin >> a >> b;
cout.precision(9); // 정수포함 9자리로 설정
cout << fixed; // 소수점 아래 9자리로 고정
cout << a/b;
cout.unsetf(ios::fixed); // fixed 해제
return 0;
}
참고