서론: 로켓을 폭발시킨 0.000001의 오차
1991년, 미군의 패트리어트 미사일이 요격에 실패하여 아군 기지에 떨어지는 참사가 있었습니다. 원인은 놀랍게도 0.000000095초의 계산 오차 때문이었습니다.
우리는 0.1 + 0.2 = 0.3이라고 확신합니다. 하지만 컴퓨터에게 시켜보면 0.30000000000000004라는 기괴한 답을 내놓습니다. 컴퓨터는 완벽하지 않습니다. 특히 소수(Decimal)를 다룰 때 그렇습니다.
오늘 22편에서는 NASA 엔지니어들이 가장 두려워하는 적, '부동소수점(Floating Point)의 오차'와 그 해결책에 대해 알아봅니다.
본론 1: 0과 1로 소수를 표현하는 한계
컴퓨터는 모든 것을 2진법(0과 1)으로 저장합니다. 정수는 완벽하게 변환되지만, 소수는 다릅니다.
- 10진수 0.5 -> 2진수 0.1 (딱 떨어짐)
- 10진수 0.1 -> 2진수 0.0001100110011... (무한소수!)
마치 10진수에서 1/3을 0.3333...으로 완벽히 적을 수 없는 것처럼, 컴퓨터도 0.1을 완벽하게 저장할 수 없습니다. 어쩔 수 없이 뒷부분을 잘라내서 저장하는데, 여기서 미세한 오차가 발생합니다.
본론 2: 오차가 쌓이면 재앙이 된다
"0.000001 차이가 뭐 그리 대수냐"라고 할 수 있습니다. 하지만 이 계산이 1초에 100번씩, 100시간 동안 반복된다면? 그 오차는 수백 미터, 수 킬로미터로 커집니다.
화성 탐사선이 궤도 진입 시 1km만 빗나가도 우주 미아가 됩니다. 그래서 금융권이나 정밀 공학에서는 `float` 대신 오차가 훨씬 적은 `double`을 쓰거나, 아예 정수로 변환해서 계산하는 테크닉을 사용합니다.
결론: 절대 '같다(==)'라고 쓰지 마라
프로그래밍에서 소수점 계산을 할 때 if (a == 1.0) 처럼 '같다'는 비교는 금물입니다. 오차 때문에 영원히 같아지지 않을 수 있습니다.
대신 "차이가 아주 작으면 같다(Epsilon Comparison)"고 판단해야 합니다. 이 작은 습관이 여러분의 프로그램을 '정밀 공학'의 수준으로 끌어올립니다.