본문 바로가기

개발 상식

부동 소수점의 한계

반응형
SMALL

가끔 부동 소수점을 표현하다가 발생하는 오차 때문에 곤혹을 치른 적이 있으셨나요? 아마 알고리즘 문제를 풀 때 가장 많이 마주치는 문제일 것입니다. 비교를 한다던가, 비교를 한다던가, 비교를 할 때 말이죠.

 

이 문제의 경우엔 많은 사람들이 겪었지만, 이유는 잘 모르고 있더라고요. 그래서 이 글에서 한 번 알아보도록 하겠습니다.


참고로 이 개발 상식은 이름만 들어도 아는 유명 IT 회사의 면접 질문 중 하나였습니다. (따끈따끈한 2019년 면접 질문) 그러니 취업 준비생이라면 꼭 알고 가셔야겠죠 !?


print(0.1 + 0.2)

Python에서 과연 위의 값을 출력하면 어떤 값이 뜰까요? 아마 0.3이라는 값을 먼저 떠올렸을거지만, 우리의 멍청한 컴퓨터는 0.3을 출력해내지 않습니다.

 

제 컴퓨터에서는 0.3000000119라는 값이 뜨고, 다른 분들의 경우엔 0.30000004라는 값을 띄우기도 했습니다. 즉, 정확한 0.3의 값이 아닌 오차가 발생했다는 것입니다.

에라이

왜 그럴까요?


이를 알기 위해선 컴퓨터가 어떻게 연산을 하는지 다시 한 번 살펴볼 필요가 있습니다. 컴퓨터에서 소수는 밑(base)가 2인(이진) 소수로 표현됩니다.

 

예를 들어, 소수 0.125 = 1/10 + 2/100 + 5/1000의 값을 가지는데, 같은 방식으로 이진 소수 0.001는 값 0/2 + 0/4 + 1/8을 가지게 됩니다. 이 두 소수는 같은 값이지만, 밑이 다르다는 차이를 가지고 있습니다.

 

여기서 문제가 발생합니다. 대부분의 십진 소수는 정확하게 이진 소수로 표현할 수 없습니다. 사실 십진 소수 역시 분수 1/3을 정확하게 표현할 수가 없죠. 근사 값을 표시할 뿐

 

같은 방식으로 아무리 많은 자릿수를 사용해도, 십진수 0.1은 이진 소수로 정확하게 표현될 수 없습니다.

0.0001100110011001100110011....

그렇기에 실제 Python에서 0.1을 출력하면 아래와 같이 표시가 됩니다.

printf(0.1)

0.1000000000000000055511151231257827021181583404541015625

아 물론 파이썬은 반올림된 값을 대신 표시하여 숫자를 다루게 만들지만, 실제로 저장된 값은 이진 소수임을 기억하시길 바랍니다.

 

그렇다면 하나의 문제 과연 0.1 + 0.1 + 0.1 == 0.3이라는 조건문의 답은 무엇일까요? 답은 False입니다. 앞서 말했 듯 0.1이라는 값을 정확하게 표현할 수 있는 방법이 존재하지 않으며, 이를 더할 시에 발생하는 오차가 존재하기 때문에, 비교를 할 수 없습니다.

모든 것을 설명하는 짤


이처럼 컴퓨터가 보여준 환상에 의존만 하다보면, 분명 문제가 발생하는 구간이 올 것입니다. 저도 그랬구요. 그러니 이러한 원인을 파악하시고, 어디서든 아는 척을 할 수 있길 바랍니다.

 

이상 부동 소수점의 한계였습니다 ^_^

반응형
LIST

'개발 상식' 카테고리의 다른 글

OOP  (0) 2021.03.14
Top Down vs Bottom Up  (0) 2020.06.02
컴퓨터 공학에서 헤르츠(Hz)라는 단위  (0) 2020.03.06
버전 표기법 (SemVer)  (0) 2020.02.14
재귀함수를 쓰는 이유  (12) 2019.12.27