(구) 자료/면접을 위하여

[5] 부동 소수점(floating Point)

뜐뜐뜐 2018. 3. 1. 19:24

오늘은 부동소수점입니다.


왜 갑자기 부동소수점을 하느냐.. 면접 관련해서 질문 나오는 기업이 있었기도 했고, 백준 문제 풀다가도 나왔기 때문이죠.


* 이 포스팅의 모든 내용과 그림은 TCPSchool을 참고하여 정리하였습니다.


* 컴퓨터에서 실수를 표현하는 방법?

- 우리는 숫자쓰다가 중간에 점 하나 찍으면 소수가 되지만, 컴퓨터는 그렇지 않습니다. 0과 1만을 알고 있을 뿐이죠.


- 현재 컴퓨터가 소수점을 나타내는 방식은 고정 소수점(Fixed Point) 방식과 부동 소수점(Floating Point)방식이 존재합니다.


1. 고정 소수점(Fixed Point)

개념

- 말 그대로, 소수점이 찍힐 위치를 미리 정해놓고 소수를 표현하는 방식입니다.


- 보통 실수는 정수 + 소수로 표현합니다.

예시

- 예를 들어, -3.14라는 소수를 표현하기 위해서는 다음의 세 가지 요소가 필요로합니다.

1) 음수와 양수를 나타내줄 부호 (-)

2) 정수부 (3)

3) 소수부 (0.14)

- 그래서 위의 숫자를 32bit에서 나타내면 아래의 그림과 같습니다.

장점?

- 실수를 정수부와 소수부로 분할표현해서 비교적 단순합니다.

단점?

- 너무 단순해서 치밀하지도 않고, 효율적이지도 못합니다.


- 정수부는 15bit, 소수부는 16bit로 자리수가 그다지 크지 않기 때문에, 표현의 범위가 생각보다 넓지 않습니다.


- 이 방식으로는 간단한 성적 처리 조차도 힘겹기 때문에 잘 사용되지 않습니다.


2. 부동 소수점(Floating Point)

- 고정 소수점의 한계를 해결해줄 부동 소수점입니다.


개념

- 고정 소수점과는 달리, 실수를 가수부 + 지수부로 나누어 표현합니다.


- 가수 : 실수의 실제값을 표현


- 지수 : 크기를 표현, 가수의 어디쯤에 소수점이 있는지를 나타냄.


- 즉, 지수의 값에 따라 소수점이 움직이기 때문에 이 방식으로 실수를 표현 하는 방법을 부동소수점이라고 합니다.


예시

- 고정 소수점과의 차이가 보이십니까?


- 소수점의 위치가 고정되어 있지 않고, 유동적으로 움직이게 됩니다.


장점?

- 고정 소수점과는 다르게, 표현할 수 있는 수의 범위가 굉장히 넓어집니다.

   (현재 모든 프로그래밍 언어, 그래픽, 공학 프로그램등이 준수하는 국제 표준 IEEE-754로 지정되어 있음)


- 가수부가 지수부보다 길어서 정밀도가 비교적 충분합니다.


단점?

- 하지만 그 정밀도가 무한하지는 않습니다.


- 예를 들어, 1.23을 부동소수점으로 표현할 수 있는 방법은 굉장히 여러가지가 나올 수 있습니다.


- 이것이 의미하는 바가 뭘까요? 오차가 발생할 수 있음을 의미합니다.


- 이를 해결할 방법으로, 소수점이 항상 가수의 첫 번째와 두 번째 사이에만 존재하도록 정규화 하는 방법이 있습니다.

   ex) 12.23 => 1.223 x 10, 132.4 => 1.324 x 10^2


자 그럼, 제가 이 부동 소수점을 들고온 근본적 이유인 백준 문제를 보시겠습니다.




시간 제한메모리 제한제출정답맞은 사람정답 비율
1 초128 MB294839729921.251%

문제

체조나 다이빙 등의 경기에서 일부 심판이 자기가 좋아하는 선수에게 높은 점수를, 싫어하는 선수에게 낮은 점수를 주는 경우가 종종 있었다. 따라서 심판들이 주는 점수의 평균점수를 선수에게 주게 되면 공정하지 않은 경우가 생길 수 있다. 이를 방지하기 위하여 절사평균이나 보정평균을 사용한다. 예를 들어 심사위원 일곱 명이 다음과 같이 점수를 주었다고 하자.

9.3, 9.5, 9.6, 9.8, 9.1, 5.0, 9.3

전체의 합이 61.6이 되므로 평균은 8.8이 된다. 이 평균점수는 한 심판이 다른 심판에 비하여 아주 낮은 점수인 5.0을 주어서 나온 결과로, 선수는 매우 불공정하다고 느낄 것이다.

위의 점수를 작은데서 큰 순서로 정렬하면 5.0, 9.1, 9.3, 9.3, 9.5, 9.6, 9.8 이 된다.

이때 절사평균(7, 2)는 정렬된 전체 점수 일곱 개 중 양쪽 끝에서 두 개씩을 제외하고 난 9.3, 9.3, 9.5의 평균인 9.37이 된다(소수점이하 셋째 자리에서 반올림). 또 보정평균(7, 2)는 정렬된 전체 점수 일곱 개 중 양쪽 끝에서 각각 두 개를, 남은 점수 중 가장 가까운 것으로 교체한 9.3, 9.3, 9.3, 9.3, 9.5, 9.5, 9.5의 평균으로 9.39가 된다(소수점이하 셋째 자리에서 반올림).

N개의 점수와 양쪽에서 제외하는 개수 K 값이 주어졌을 때 절사평균(N, K)와 보정평균(N, K)를 계산하는 프로그램을 작성하시오.

입력

첫째 줄에 전체 점수의 개수 N과 제외되는 점수의 개수 K가 빈칸을 사이에 두고 주어진다. N은 3 이상 100,000 이하의 자연수이다. K는 0 이상 (N/2)-1 이하로 주어진다. 그 다음 N줄에는 각 심판의 점수가 한 줄에 하나씩 주어진다. 점수는 0 이상 10 이하의 실수로 소수점이하 첫째 자리까지 주어진다.

출력

첫째 줄에 절사평균(N, K)를, 둘째 줄에 보정평균(N, K)를 각각 소수점이하 셋째 자리에서 반올림하여 둘째 자리까지 출력한다. 예를 들어 결과값이 9.667인 경우 9.67로, 5인 경우 5.00으로, 5.5인 경우에는 5.50으로 출력한다.



위에서 말했던 것처럼, 부동소수점 표현 방식은 오차가 존재할 수 있기 때문에 출력 값이 항상 일정하지 않을 수 있습니다.


0.0000000001의 차이로 값이 바뀌는 경우, 1.0이 0이 될 수도, 1이될 수도 있기 때문이죠.


그래서 출력 값에 0.0000000001을 더해주면 이러한 값의 이탈을 막아 정답을 출력할 수 있습니다.


물론, 더해주는 값은 문제의 출력 조건에 따라 유동적으로 변할 수 있습니다. (2^(-8) 으로 해보니까 되고 -7승은 안되네요)