블램의 일상 IT카페

백준 1008번 [A/B] - 문제를 이해해보고 풀어보자! 본문

IT/알고리즘 문제 풀이

백준 1008번 [A/B] - 문제를 이해해보고 풀어보자!

ble_ram 2022. 11. 14. 20:44

백준 문제 1008번 풀기전에 문제를 이해해보자!

*이 글은 C언어 를 중심으로 작성했습니다.

*최대한 힌트 위주로 글을 작성하였습니다.  그 이유는 단순히 답만 보고 클론코딩하기보다

여러분들이 스스로 힌트를 얻고 문제를 풀었으면 하는 마음입니다. ^^7

 

백준 1008번

 

우선 나뿐만이 아니라 모두가 그렇듯 문제가 이해안되서 못푸는 경우가 많을 것 같다.

(맞겠지?... 나만 그랬던거 아니겠지? ㅋㅋ;;)

 

 

 

 

내가 문제를 틀린이유.


우선 내가 문제를 이해하고 처음으로 구현한 코드는 아래와 같다.

 

#include <stdio.h>
int main(){
	int a,b;
		
	scanf("%d %d", &a, &b);
    
	int div = (double)a/(double)b;
    
    printf("%lf", div);
	
	return 0;
}

물론 이건 첫번째 실수다.

1. div 변수를 추가하여 코딩한것

2. 상대오차를 고려하지 않은 것

 

 

이제 두번째 실수다. 여기서부턴 따로 변수를 추가하지 않아야 된다는 걸

알고 작성하였다.

 

#include <stdio.h>
int main(){
	int a,b;
		
	scanf("%d %d", &a, &b);
	
	printf("%f", (float)a/(float)b);
    /*물론 b앞 (float)를 안 붙여보기도 했다.*/
	
	return 0;
}

이건 내가 모르는게 너무 많았다.

1. 상대오차 고려 안 한것

2. float 자료형과 double 자료형의 오차범위 생각 안한것.

 

 

 

 

 

 

이제 문제를 이해해보자.


아마 대부분이 나와 같은 이유로 틀리지 않았을까 싶다.

 

 

다들 float와 double형의 차이인 오차범위는 다들 알거라 생각한다.

 

(모른다면 대충 float형은 오차범위가 대략 10의 -7승 이라보시면 되고

double형은 대략 10의 -15승 까지라 보면 된다.)

 

이제 대충 문제를 맞추지 못한 이유와 자료형에 대해 파악했으니 문제를 분석해보자.

 

 

여기서 나는 절대오차 OR 상대오차가 '10의 -9승 이하'이면 된다길래

 

당연히 10의 -9승 밑으로만 나오면 되는 줄 알았다.

거기다 소수점 9번째 까지 출력한다는 것이 아니라하여

이것은 더욱 확신이 되었다.

 

즉 9번째 이하로만 결과가 출력되면 된다는 것.

 

그랬더니 어?

 

정수를 입력받아 결과를 어찌저찌 실수로 출력하겠금 만들었다.

(float형, double형 참고 - 대충 *자료형 변환 참고)

 

[추가로 : 정수 / 정수는 컴퓨터가 정수로 출력한다. 하지만 우리가 원하는 건 실수값도 출력되겠금 하는 것이기에

정수/실수 OR 실수/정수 OR 실수/실수 로 만들어주면 된다.]

(*하지만 입력값이 정수여야기에 실수/실수는 출력값에 적용시켜야한다.)

 

 

 

하지만 아무리해도 결과가 나오지 않았다.

 

그래서 폭풍 구글링을 하였다 ㅋㅋ~~~~!!!!!!!

 

나는 내가 지금 문제를 풀지 못하는 이유가 문제를 즉 저 부분을 이해하지 못하였다 생각한 것 이기에

저 부분을 이해하기로 하였다.

 

즉 이해하고 알아낸바 

 

 

 

 

 

상대오차 이해와 문제 이해


 

상대오차는 내가 얻어낸 결과값 즉 '출력값과 문제의 정답의 차' 이다.

(흠 글 다쓰고 보는데 이거 알고보니 다 나와있었네 ㅋㅋㅋ)

 

예를 하나 들어보겠다.

 

10/3 이라는 문제가 있다. 이 문제는 정답이 3.333333333(9번째까지)이다.

그렇다면 내가 코딩하여 얻어낸 값이 3.333333254라면

 

과연 상대오차는 몇이겠는가?

 

내가 직접 계산기 돌려본바. 

 

 

상대오차는 7.9 * 10^-8 이다.

 

즉 문제에서 조건으로 제시한 10^-9 즉 '1 * 10^-9승 이하' 를 아득히 뛰어넘었다.

즉 오차범위가 조건보다 더 크게 차이나는 것.

그러므로 이 내가 낸 값은 정답이 아닌 것이 된다.

 

여기서 몇몇은 눈치 채신분들도 있을거라 생각한다.

 

저 3.333333254 이 값은 float함수를 사용하여 나온 10/3 의 값이다.

 

float 함수는 유효숫자 7자리 이내 사용

double 함수는 유효숫자 15자리 이내 사용 

이므로

 

3.333333254.라는 값은 내가 소숫점 9자리까지 결과가 나오게 임의로 설정한것이다.

 

그럼 오차범위에 대한 문제의 조건을 이해하였는가?

 

결국 출제자가 이 문제를 만들고 의도한 것은

 

주어진 오차범위(10 ^ -9) 내로(이하로)[문제정답 - 나의 코드 출력값]이 나오게 하기위해서 이다.

그래서 이 조건을 만족시키기 위한 자료형인 float 와 double을 알맞게 사용할 수 있는가? 를 묻는 것이다.

 

(결과출력이 실수로 밖에 나올 수 없는 것은 정수/정수는 4/2를 했을때 2가 나온다.

만약 10/3을 정수로 출력하면 3으로 소수점이 끊겨나오게 될 것이다.

하지만 10/3을 실수형으로 출력하면 소수점까지 나오게 되고 4/2를 하더라도 4.0/2.0이든 4/2.0이든

실수값으로도 정수형을 표시할 수 있어 결과값은 실수형을 쓸 수 밖에 없다.

정수형이야 입력값에 필수적인 조건이기에 처음부터 실수형으로 쓸 수 없는 것.) 

 

즉 나같은 경우엔 저 오차범위 즉 상대오차나 절대오차를 소수점 자리라는 시각으로 보았기에

오차 즉 무언가의 차라는 것을 생각하지 못한것이다.

(사실 float, double 기억이 안나서 교재를 찾아봤단건 비밀.. ㅡㅡ;;)

 

반대로 double형 함수로 바꿔서 계산해주면 (9번째까지) 3.333333333으로 오차범위가 확 줄어든다.

 

여기까지가 문제에 대한 이해이자 힌트입니다.

 

이후는 정답 풀이이니 여기까지만 보고 직접 풀어보시길 바랍니다. !!

(풀다가 도저히 안풀리면 오세용~)

 

 

 

 

마지막으로 이제 문제를 다시 읽어보고 풀이해보자.


<문제조건>

  1. 입력값은 정수
  2. 실제 정답과 절대오차 또는 상대오차가 10 ^ -9 이하

 

이제 답을 구해보자.

 

#include <stdio.h>
int main(){
	int a,b;
		
	scanf("%d %d", &a, &b);
	
	printf("%.9lf", (double)a/b);
	
	return 0;
}

(추가로 .9lf 즉  9자리까지 꼭 지정해 줘야하나요? 궁금할 수 있을텐데

double형의 오차 유효자리는 15자리 이내이기에 문제 조건에 의하면 

꼭 9자리 이상을 출력해줘야 한다.)

 

 

이렇게도 된다.!

#include <stdio.h>
int main(){
	int a,b;
		
	scanf("%d %d", &a, &b);
	
    printf("%.10lf", (double)a/b);
	
	return 0;
}

 

끝입니다.!

언제나 잘못된 지식은 피드백 할테니 딴지걸기 환영입니다.!!!!!!

 

 

 


*추가로*

 

제가 이 문제를 풀기위해 이리저리 많이 구글링하고 몇시간씩 쏟았습니다. 하하..

물론 문제를 풀기위해 비효율적인 건 맞지만 그래도 궁금한데 뭐 어쩌겠습니까.

 

제가 찾아본 바로는 이 문제는 알고리즘 지식과도 묶을 수 있고, 다양한 분들의 풀이를 보면

저 풀이는 정말 애기가 푼 수준이더군요 ㅎㅎ

 

이 문제에 대해 더 심화적으로 알고 싶으시다면 '부동 소수점' 에 대해 공부하시면 될 것 같습니다.

(정말 간단해보이는 문제조차 이런 심화학습이 될 줄이야 이거 완전 수학 공식 증명이잖아~!?)

이에 대한건 제가 아직 학부생이라 알고리즘 자료구조 지식이 부족하기에 누구나 쉽게 이해 할만하게 

설명하였습니다.

(초장부터 이런 내용이 나오면 아무도 안볼것 가트,,,, 흠흠...)

 

암튼 제가 너무 부족한걸 느낍니다.

 

더 열심히 공부해서 더 좋은 글 많이 쓰겠습니다.~~!!!!!!!

 

Comments