SW개발

0.1 을 100 번 더해도 10이 되지 않는다?

박종명 2023. 9. 27. 08:44
728x90

이 글은 제가 과거에 운영했던 사이트인 http://dotnet.mkexdev.net 의 글을 옮겨온 것입니다.
그 전에 운영했었던 사이트(mkex.pe.kr)은 흔적도 없이 사라 졌습니다. 그속의 글들도 모두...
그래서 이 사이트도 사라지기 전에 옮기고 싶은 글을 조금씩 이 블로그로 이동시키려 합니다.
(원본글) http://dotnet.mkexdev.net/Article/Content.aspx?parentCategoryID=2&categoryID=9&ID=97

---

너무나도 유명한 문구가 아닌가 싶습니다.
기초 C언어 공부할때나 프로그래밍 원리 같은 공부할때 꼭 등장하는 말입니다. 저도 그 말을 인용해 봤습니다.
 
이 말은 컴퓨터의 실수 표현 방식과 그에 따른 오차에 관한 말인데요.. 실제로 실수형 데이터의 연산에는 오차가
발생합니다. (직접해보세요.. 0.1 , 100 번 더하기)
 
이미 우리는 앞에 2진수로 표현된 수를 10진수로 변환하는 방법을 알고 있습니다. 그러면 2진수로 표현된 소수를
10진수로 변환하는 방법은요??? ... 마찬가지 입니다.
 
EX>2진수 1.01 을 10진수로 만들어 보겠습니다.
(2진수) 1.01 => 1*2의0 + 0*2의-1승 + 1*2의-2승 = 1 + 0 + 0.25 = 1.25 (10진수)
이렇듯 2진수를 10진수로 표현할 때는 소수점을 기점으로 2의 (+,-)승을 해나가면 됩니다.
 
 
그렇다면 10진수 소수인 0.1 은 2진수로 어떻게 표현될까요???
소수점 이하 자리는 2의 마이너스 승이므로 2의 -1 승부터 차례로 해 보겠습니다

2의-1승 = 0.5 , 2-2 = 0.25 , 2-3 = 0.125 , 2-4 = 0.0625 ………

0.125 에서 바로 0.0625 로 넘어가 버렸습니다. 0.1은 나오지도 않았는데 말이죠..
물론 비트 자릿수를 늘려 이 들 숫자의 조합으로 0.1 에 가까운 수를 찾을 수는 있습니다만, 0.1이 아닌 근사값이
됩니다. 위의 산술과정은 비트자릿수를 하나씩 늘려서 0보다 큰 제일 작은 수를 나타낸 것인데요..

이런 방식이 아니더라도 소수점 이하 4비트를 가지는 메모리에서 표현되는 수를 다시 한번 보겠습니다.
소수점 이하 4비트를 가지는 2진수의 제일 작은 수 : 0.0000 => 10진수 0
소수점 이하 4비트를 가지는 2진수의 그 다음 작은 수 : 0.0001 => 10진수 0.0625
즉, 이 메모리로는 10진수 0과 0.0625 사이의 값은 표현할 수가 없습니다.
비트 수를 더 늘리면 더 좁은 간격의 수가 나올 수 는 있겠습니다만..

이렇듯 컴퓨터는 10진수 실수를 표현하는데 오차를 가집니다.
10진수에 해당하는 실수 값에 근사값을 나타낼 수 있을 뿐이지요.. 
 
 
결론적으로 0.1 이라는 값을 가지는 변수를 선언하면 그 변수에는 실제 0.1이 들어가는 것이 아니라 0.1의 근사값이
저장됩니다. 즉, 0.1의 근사값을 100번 더해봤지 10이 될리 없는 것입니다.
실제로 10진수 0.1을 2진수로 변환하면 0.00011001100....... (이하 1100 반복)이 됩니다
이런 수를 수학에서는 순환소수라 합니다.
대표적인 순환소수는 1/3 이 있습니다. 1/3 을 소수로 표현하면 0.33333.....(이하 3반복) 이 됩니다

참고>>
위의 내용은 문제를 간단하게 표현하기 위해 그리고 오차가 나는 이유를 이해하기 위해  2진수 소수 표현방식을 나타 냈습니다. 그러나 실제로 컴퓨터는 실수 표현을 단순히 소수점을 가진 2진수로 표현하지는 않습니다.
미리 말씀드리자면 일정한 식을 가지고 비트를 각 영역별로 나누어 저장,표현합니다. 이에 대해선 다음에 알아봅니다