최근 코딩을 하거나 특정 프로그램을 사용하다 보면 ‘이건 왜 결과가 이렇게 나오지?’ 하고 고개를 갸웃거릴 때가 많으셨을 거예요. 특히 숫자를 다루는 작업에서 예상치 못한 미세한 오차가 발생하면, 작은 버그처럼 느껴지기도 하죠. 저도 개발을 하면서 이런 상황에 마주칠 때마다 답답함을 느끼곤 했는데요, 그 배경에는 바로 ‘STATUS_FLOAT_INEXACT_RESULT’ 같은 알쏭달쏭한 코드들이 숨어 있답니다.
단순히 오류라기보다는 부동소수점 연산의 미묘한 특성에서 비롯되는 현상이라 정확히 이해하는 것이 정말 중요해요. 시스템의 안정성을 넘어 정밀한 데이터 처리까지 영향을 미치는 이 코드, 대체 무엇이며 어떻게 마주해야 할까요? 아래 글에서 자세하게 알아봅시다.
왜 내 숫자는 항상 미묘하게 틀릴까?
눈에 보이지 않는 작은 오차의 시작
제가 처음 개발을 시작했을 때, 참 신기했던 경험이 있어요. 분명히 제가 입력한 숫자대로 계산하고 저장했을 텐데, 결과값을 보면 소수점 몇째 자리에서 살짝 다른 거예요. 예를 들어, 0.1 을 10 번 더했는데 1.0 이 아니라 0.9999999999999999 가 나오는 식이었죠. ‘내가 뭘 잘못했나?’ 싶어서 코드를 몇 번이고 다시 들여다봤지만, 논리적인 오류는 찾을 수 없었어요. 이런 상황에 마주치면 정말 당황스럽고, 버그인가 싶어 머리를 싸매게 되죠. 이게 바로 컴퓨터가 숫자를 표현하는 방식, 특히 부동소수점(Floating-Point) 연산의 특성 때문에 발생하는 현상이에요. 우리는 10 진수로 익숙하지만, 컴퓨터는 모든 걸 2 진수로 처리하니까요. 이 변환 과정에서 정확히 표현할 수 없는 숫자들, 즉 2 진법으로 무한히 반복되는 소수들이 생겨나고, 컴퓨터 메모리는 한정되어 있으니 그 일부를 잘라내면서 미세한 오차가 발생하게 된답니다. 처음엔 정말 답답했는데, 이 원리를 알고 나서는 “아, 이게 컴퓨터의 한계이자 자연스러운 현상이구나” 하고 이해하게 됐어요. 덕분에 숫자를 다룰 때 더 신중하게 접근하는 습관을 들이게 되었죠.
우리가 몰랐던 2 진수의 세상
사람은 0.1 이나 0.25 같은 소수점을 너무나 자연스럽게 사용하잖아요? 그런데 컴퓨터 내부에서는 이 숫자들을 2 진수로 바꿔서 저장해야 해요. 10 진수 0.5 는 2 진수 0.1 로 딱 떨어지지만, 10 진수 0.1 은 2 진수로 변환하면 0.0001100110011… 처럼 무한히 반복되는 숫자가 된답니다. 마치 1/3 을 10 진수로 표현하면 0.3333… 하고 끝없이 이어지는 것과 같아요. 컴퓨터 메모리는 한정되어 있으니, 이 무한한 숫자를 어디선가는 잘라내야만 하겠죠? 여기서 바로 미세한 오차가 발생하게 되는 거예요. 처음에는 이 사실을 몰라 ‘내가 코드를 잘못 짰나?’ 하고 자책했었는데, 사실은 컴퓨터가 숫자를 표현하는 방식의 근본적인 한계였던 거죠. 이 경험을 통해 개발자는 단순히 코드를 잘 짜는 것을 넘어, 컴퓨터의 작동 방식에 대한 깊이 있는 이해가 정말 중요하다는 것을 깨달았어요. 이런 배경 지식 없이는 아무리 코드를 잘 짜도 예측하지 못한 문제가 생길 수 있으니 말이죠.
부동소수점, 이 친구와 친해지기
이해하면 보이는 연산의 마법
부동소수점은 사실 우리 일상생활에서도 비슷한 개념을 찾아볼 수 있어요. 예를 들어, 거대한 우주의 거리를 측정할 때 미터 단위로 정확히 재기보다는 ‘광년’ 같은 큰 단위를 사용해서 대략적인 값을 표현하잖아요? 그리고 아주 작은 미생물의 크기를 이야기할 때는 ‘마이크로미터’ 같은 단위를 써서 소수점 아래로 한참 내려가는 숫자를 다루고요. 이처럼 컴퓨터도 아주 크거나 아주 작은 숫자를 효율적으로 다루기 위해 부동소수점 방식을 사용해요. 정수 부분과 소수 부분, 그리고 지수 부분을 나누어 표현함으로써 넓은 범위의 숫자를 다룰 수 있게 되는 거죠. 하지만 이 과정에서 앞서 언급했듯이 정밀도의 한계가 발생할 수밖에 없어요. 이걸 이해하고 나면, “아, 그래서 0.1 + 0.2 가 정확히 0.3 이 아닐 수도 있구나” 하고 고개를 끄덕이게 된답니다. 단순히 버그라고 생각했던 부분이 컴퓨터 과학의 깊은 원리와 연결되어 있다는 걸 알게 됐을 때, 정말 흥미로웠어요. 컴퓨터가 숫자를 다루는 방식을 이해하는 건 마치 새로운 언어를 배우는 것만큼이나 흥미진진한 일 같아요.
오차를 최소화하는 현명한 전략
그렇다면 이런 미세한 오차를 그냥 내버려 둬야 할까요? 물론 아니죠! 상황에 따라 이 오차가 중요한 결과를 초래할 수도 있기 때문에, 개발자는 이를 인지하고 적절히 처리해야 해요. 예를 들어, 금융 계산처럼 아주 높은 정밀도가 요구되는 분야에서는 부동소수점 대신 고정소수점(Fixed-Point) 방식을 사용하거나, 정수형으로 바꿔서 계산하는 등의 방법을 활용하기도 합니다. 아니면 오차 허용 범위(Tolerance)를 설정해서, 두 숫자가 완전히 같지 않더라도 특정 오차 범위 내에 있다면 같은 것으로 간주하는 로직을 적용할 수도 있고요. 저도 한때 정밀한 과학 계산을 다루는 프로젝트를 진행할 때, 이 부동소수점 오차 때문에 밤새 골머리를 앓았던 적이 있어요. 그때 여러 문헌을 찾아보고 선배 개발자들의 조언을 들으면서, 단순히 숫자를 그대로 쓰는 것이 아니라 ‘어떻게 써야 안전하고 정확한가’를 고민하는 법을 배웠죠. 이런 노력이 쌓여야만 안정적인 프로그램을 만들 수 있답니다. 문제를 직접 겪어보고 해결하는 과정에서 진정한 노하우가 생기는 것 같아요.
예상치 못한 오차, 버그가 아닐지도?
컴파일러가 던지는 경고의 메시지
개발을 하다 보면 간혹 컴파일러나 런타임 환경에서 부동소수점 연산과 관련된 메시지를 만나게 될 때가 있어요. (물론 직접적으로 같은 이름으로 보이지 않을 때도 많죠!) 처음에는 ‘이게 무슨 에러지? 내 코드가 뭔가 잘못됐나?’ 하고 덜컥 겁을 먹기 쉽습니다. 하지만 사실 이런 메시지들은 대부분 ‘부동소수점 연산 결과가 정확하지 않을 수 있다’는 일종의 경고에 가까워요. 즉, 연산 자체는 성공적으로 수행되었지만, 그 결과가 2 진수로 정확하게 표현될 수 없는 값이라는 의미인 거죠. 마치 “너 지금 소수점 아래에 무한히 반복되는 숫자를 다루고 있는데, 이걸 유한한 공간에 담으려니 조금 잘려 나갈 수밖에 없어!” 하고 알려주는 것과 같아요. 저는 처음 이 메시지를 접했을 때, 마치 컴퓨터가 저에게 직접 말을 거는 듯한 느낌을 받았어요. 단순히 에러 메시지를 외우는 것이 아니라, 그 메시지가 담고 있는 의미를 깊이 파고들수록 개발 실력이 더 탄탄해지는 것 같아요. 이런 작은 경고 하나하나가 결국 더 나은 소프트웨어를 만드는 길잡이가 되는 셈이죠.
다양한 부동소수점 연산 예외들
부동소수점 연산에서는 ‘정확하지 않은 결과’ 말고도 여러 가지 예외 상황들이 발생할 수 있어요. 예를 들어, 너무 큰 숫자를 다루다가 컴퓨터가 표현할 수 있는 범위를 넘어서면 오버플로우(Overflow)가 발생하기도 하고, 반대로 너무 작은 숫자를 다루다가 거의 0 에 가까운 값으로 사라져 버리는 언더플로우(Underflow)가 생기기도 합니다. 또한, 0 으로 나누는 것처럼 수학적으로 정의되지 않는 연산을 시도하면 ‘유효하지 않은 연산(Invalid Operation)’ 에러가 발생할 수도 있죠. 이런 예외 상황들은 단순히 연산이 실패했다는 것을 넘어, 프로그램의 안정성과 데이터의 신뢰성에 치명적인 영향을 줄 수 있어요. 저도 한 번은 오버플로우 때문에 계산 결과가 엉뚱하게 나와서, 한참 동안 디버깅하느라 고생했던 적이 있답니다. 결국, 이러한 예외들을 미리 예측하고 적절히 처리하는 것이 견고한 프로그램을 만드는 핵심이라는 것을 깨달았죠. 이처럼 숫자 하나를 다루는 데도 개발자의 세심한 주의가 필요하다는 걸 경험을 통해 알게 됐습니다.
부동소수점 연산 예외 유형 | 설명 | 예상 결과 |
---|---|---|
정확하지 않은 결과 (Inexact Result) | 연산 결과가 이진수로 정확히 표현될 수 없는 경우. (예: 0.1 + 0.2) | 미세한 소수점 오차 발생 |
오버플로우 (Overflow) | 연산 결과가 표현 가능한 최대값을 초과하는 경우. | 무한대 (Infinity) 또는 최대값으로 처리 |
언더플로우 (Underflow) | 연산 결과가 표현 가능한 최소값보다 작아 거의 0 이 되는 경우. | 0 또는 0 에 가까운 값으로 처리 |
유효하지 않은 연산 (Invalid Operation) | 수학적으로 정의되지 않는 연산 (예: 0 으로 나누기, 음수의 제곱근) | NaN (Not a Number) 발생 |
정밀한 계산을 위한 개발자의 꿀팁
금융 및 과학 계산, 특별한 주의가 필요해!
앞서 말씀드렸듯이 모든 연산에서 완벽한 정밀도가 필요한 건 아니지만, 특정 분야에서는 아주 작은 오차도 큰 문제로 이어질 수 있어요. 특히 금융 애플리케이션에서는 단 1 원의 오차도 허용되지 않죠. 제가 예전에 금융 관련 프로그램을 개발할 때, 부동소수점 오차 때문에 고객 계좌 잔액이 미세하게 틀어지는 시뮬레이션을 보고 얼마나 놀랐는지 몰라요. 그때부터는 단순한 이나 타입을 사용하는 대신, (Java)이나 (Python, C#)과 같은 정밀한 십진수 연산을 지원하는 자료형을 적극적으로 활용하기 시작했어요. 이런 자료형들은 내부적으로 숫자를 정수 형태로 관리하며 소수점 위치를 따로 추적하기 때문에, 부동소수점 오차 없이 정확한 계산이 가능하답니다. 물론 연산 속도가 일반 부동소수점 연산보다 느리다는 단점도 있지만, 정확성이 최우선인 상황에서는 반드시 고려해야 할 선택지라고 할 수 있어요. 개발자는 언제나 ‘어떤 도구를 언제 사용해야 하는가’를 고민해야 하는 숙명을 가진 것 같아요. 이처럼 상황에 맞는 최적의 도구를 선택하는 것이 진정한 실력이죠.
FPU 상태를 직접 제어하는 방법
때로는 아주 낮은 수준에서 부동소수점 연산을 직접 제어해야 할 때도 있어요. 특히 C/C++ 같은 언어에서는 FPU(Floating-Point Unit)의 상태를 확인하고 제어하는 함수들을 제공하죠. 예를 들어, 이나 같은 함수들을 사용하면 현재 FPU의 예외 상태(오버플로우, 언더플로우, 정확하지 않은 결과 등)를 직접 확인하고 초기화할 수 있답니다. 마치 자동차의 계기판에서 엔진 경고등이 떴을 때, 어떤 문제가 있는지 확인하고 리셋하는 것과 비슷하다고 할까요? 이런 기능들은 특히 임베디드 시스템이나 아주 성능에 민감한 저수준 프로그래밍을 할 때 유용하게 활용될 수 있어요. 저도 과거에 특정 라이브러리의 부동소수점 계산 결과가 이상하게 나올 때, FPU 상태를 직접 확인해서 어떤 예외가 발생했는지 찾아낸 경험이 있어요. 이런 디버깅 과정은 정말 힘들지만, 문제를 해결했을 때의 쾌감은 이루 말할 수 없죠. 개발자의 이런 숨은 노력들이 모여 더 견고하고 정확한 소프트웨어가 만들어지는 거 아니겠어요? 이런 깊이 있는 지식은 프로그램을 더 신뢰할 수 있게 만드는 중요한 자산이 됩니다.
컴퓨터가 숫자를 계산하는 방식의 비밀
이진법과 부동소수점의 만남
컴퓨터의 가장 기본적인 언어는 이진법, 즉 0 과 1 로 이루어져 있다는 건 다들 아실 거예요. 우리 인간이 10 개의 손가락을 써서 10 진법에 익숙해진 것처럼, 컴퓨터는 전기 신호의 켜짐(1)과 꺼짐(0)을 이용해 모든 정보를 처리하죠. 숫자를 저장할 때도 마찬가지예요. 예를 들어 정수 5 는 이진수로 101 이 되고, 10 은 1010 이 됩니다. 그런데 소수점 있는 숫자, 즉 실수(Real Number)를 이진수로 표현하는 건 조금 더 복잡해요. 여기서 부동소수점(Floating Point) 방식이 등장합니다. 이는 숫자를 “부호(Sign) + 가수(Mantissa) + 지수(Exponent)” 형태로 저장하는 방식이에요. 마치 과학 시간에 아주 큰 숫자를 1.23 x 10^5 이런 식으로 표현하는 것과 비슷하죠. 이 방식 덕분에 컴퓨터는 엄청나게 넓은 범위의 숫자들을 비교적 적은 메모리로 다룰 수 있게 됩니다. 제가 처음 컴퓨터 공학을 배우면서 이 부동소수점의 원리를 접했을 때, 마치 숫자의 세계에 숨겨진 비밀 코드를 해독하는 느낌이었어요. 알면 알수록 컴퓨터는 정말 놀라운 존재라는 생각이 들죠. 단순히 숫자를 저장하는 방식을 넘어, 효율성까지 고려한 대단한 발명이라고 할 수 있어요.
IEEE 754 표준, 전 세계의 약속
그런데 만약 모든 컴퓨터 제조업체나 소프트웨어 개발자들이 제각각의 방식으로 부동소수점 숫자를 처리한다면 어떻게 될까요? 한 컴퓨터에서 계산한 결과가 다른 컴퓨터에서는 다르게 나올 수도 있고, 프로그램이 제대로 호환되지 않는 큰 문제가 발생할 거예요. 그래서 이런 혼란을 막기 위해 국제전기전자학회(IEEE)에서 IEEE 754라는 부동소수점 표준을 만들었어요. 이 표준은 부동소수점 숫자를 저장하고 연산하는 방식을 엄격하게 정의하고 있어서, 전 세계 거의 모든 컴퓨터가 동일한 방식으로 실수를 처리할 수 있도록 해줍니다. 우리가 사용하는 대부분의 프로그래밍 언어나 하드웨어는 이 IEEE 754 표준을 따르고 있죠. 이 표준 덕분에 “내가 짠 코드가 다른 사람 컴퓨터에서도 똑같이 동작할까?” 하는 걱정을 덜 수 있게 되는 거예요. 개발자로서 이런 표준의 존재는 정말 고맙죠. 덕분에 복잡한 계산 결과의 일관성을 믿고 개발에 집중할 수 있으니까요. 이처럼 보이지 않는 곳에서 우리 개발을 든든하게 지탱해주는 표준들이 정말 많답니다. 이런 표준이 없다면 개발 세상은 정말 혼란스러웠을 거예요.
사소한 오류가 큰 문제로 이어지지 않게 하려면
단순한 무시가 부르는 나비효과
어떤 사람들은 “어차피 소수점 몇째 자리 오차인데 괜찮겠지?” 하고 부동소수점 오차를 대수롭지 않게 생각하기도 해요. 하지만 제가 경험한 바로는, 이런 사소한 오차들이 예상치 못한 큰 문제로 이어지는 경우가 생각보다 많습니다. 예를 들어, 여러 번의 반복 계산을 거치면서 작은 오차가 계속 누적되어 결국에는 최종 결과값을 완전히 왜곡시켜버릴 수도 있고요. 항공기 제어 시스템이나 의료 기기처럼 정밀도가 생명인 분야에서는 단 0.0001%의 오차도 치명적인 결과를 초래할 수 있습니다. 저는 한 번은 특정 시뮬레이션 프로그램에서 초기에는 미미했던 오차가 수만 번의 반복 계산 후에 완전히 다른 결론을 도출하는 것을 목격하고는 정말 소름이 돋았던 적이 있어요. 그때부터 “작은 오차라도 절대 무시해서는 안 된다”는 것을 뼈저리게 느꼈죠. 프로그래밍은 단순히 코드를 짜는 것을 넘어, 발생 가능한 모든 시나리오를 예측하고 대비하는 과정이라는 것을 다시 한번 깨달았답니다. 이처럼 개발자의 작은 관심 하나가 프로그램의 운명을 좌우할 수 있습니다.
테스트와 검증, 그리고 개발자의 책임
그렇다면 이런 부동소수점 관련 문제들을 어떻게 효과적으로 관리할 수 있을까요? 가장 중요한 것은 바로 철저한 테스트와 검증입니다. 특히 숫자를 다루는 로직의 경우, 다양한 입력값과 경계값(Boundary Case)을 넣어보고 예상한 결과와 일치하는지 꼼꼼하게 확인해야 해요. 필요하다면 오차 허용 범위를 설정하여 테스트를 자동화하는 것도 좋은 방법입니다. 또한, 코드 리뷰를 통해 다른 개발자들과 함께 부동소수점 연산 로직을 검토하고, 잠재적인 문제점을 미리 발견하는 것도 중요하죠. 제가 회사에서 코드 리뷰를 받을 때, 선배 개발자분들이 이런 부동소수점 관련 이슈를 날카롭게 지적해주셔서 큰 도움이 됐던 기억이 많아요. 이런 과정을 통해 개발자는 단순히 기능을 구현하는 사람을 넘어, 자신이 만든 소프트웨어의 정확성과 신뢰성을 책임지는 전문가로 성장하게 됩니다. 결국, 우리가 만드는 프로그램은 현실 세계에 영향을 미치므로, 작은 부분 하나하나에도 세심한 주의를 기울여야 한다는 것을 잊지 말아야 해요. 이러한 책임감이 바로 개발자를 빛나게 하는 요소라고 생각합니다.
글을 마치며
이렇게 부동소수점 오차에 대한 이야기를 풀어보니, 처음 개발을 시작하며 겪었던 당황스러움이 다시금 떠오르네요. 숫자가 늘 정확할 거라는 막연한 기대가 깨졌을 때의 그 혼란이란! 하지만 이런 과정을 통해 컴퓨터가 숫자를 다루는 방식의 깊이를 이해하게 되었고, 개발자로서 한 층 더 성장할 수 있었던 것 같아요. 단순히 버그라고 치부하기 쉬운 이런 현상들이 사실은 컴퓨터 과학의 근본적인 원리와 연결되어 있다는 점이 정말 매력적이지 않나요? 여러분도 부동소수점 오차를 단순히 피해야 할 대상으로 여기기보다는, 컴퓨터와 숫자의 대화 방식이라고 이해하고 현명하게 대처하는 개발자가 되시길 진심으로 바랍니다. 이 지식이 여러분의 개발 여정에 든든한 등대가 되어줄 거예요.
알아두면 쓸모 있는 정보
1. 부동소수점 오차는 컴퓨터가 10 진수를 2 진수로 변환하고 저장할 때 발생하는 미세한 정밀도 손실을 의미해요. 메모리의 한계 때문에 무한 소수를 자를 수밖에 없어 생기는 자연스러운 현상이죠.
2. 이런 오차는 금융 계산이나 과학 시뮬레이션처럼 높은 정밀도가 요구되는 분야에서 누적되어 심각한 결과를 초래할 수 있으니 주의해야 해요. 단순히 무시했다가는 큰 코 다칠 수 있답니다.
3. 정밀한 계산이 필요할 때는 (Java)이나 (Python, C#)과 같이 십진수 연산을 정확하게 지원하는 자료형을 사용하는 것이 좋아요. 일반 부동소수점 타입보다 훨씬 안전하고 정확하거든요.
4. IEEE 754 는 전 세계적으로 부동소수점 숫자를 표현하고 연산하는 방식을 표준화한 규약이에요. 이 표준 덕분에 어떤 컴퓨터에서든 일관된 계산 결과를 기대할 수 있게 된 거죠.
5. C/C++ 같은 저수준 언어에서는 이나 같은 함수를 이용해 FPU(Floating-Point Unit)의 상태를 직접 확인하고 제어하여 부동소수점 연산 예외를 처리할 수 있답니다.
중요 사항 정리
부동소수점 오차는 개발자가 반드시 이해하고 넘어가야 할 핵심 개념 중 하나입니다. 이는 단순히 버그가 아니라 컴퓨터가 숫자를 다루는 근본적인 방식에서 오는 특성이기 때문이죠. 이 오차를 제대로 이해하지 못하면 예측 불가능한 결과로 이어져 프로그램의 안정성을 해칠 수 있습니다. 특히 금융이나 과학 분야처럼 정밀도가 생명인 곳에서는 치명적인 문제를 일으킬 수 있으니, 항상 주의를 기울여야 해요. 정밀한 계산이 필요할 때는 같은 전용 자료형을 사용하고, 오차 허용 범위를 설정하여 테스트하는 등의 현명한 전략을 세우는 것이 중요합니다. 또한, IEEE 754 표준처럼 부동소수점 연산의 일관성을 보장하는 국제 표준을 알아두는 것도 큰 도움이 됩니다. 결국, 개발자의 세심한 이해와 노력이 더 견고하고 신뢰할 수 있는 소프트웨어를 만들어내는 초석이 된다는 점을 잊지 마세요. 작은 오차 하나가 큰 나비효과를 불러올 수 있다는 점을 항상 명심하고 개발에 임하시길 바랍니다.
자주 묻는 질문 (FAQ) 📖
질문: STATUSFLOATINEXACTRESULT, 이름만 들어도 어렵게 느껴지는데, 이게 대체 뭔가요? 간단하게 설명해 주실 수 있나요?
답변: 저도 처음 이 코드를 접했을 땐 머리가 지끈거렸어요. 간단히 말하면, 이건 컴퓨터가 소수점 계산(부동소수점 연산)을 했는데, 우리가 생각하는 수학적으로 ‘딱 떨어지는’ 정확한 결과가 아니라 미세하게 오차가 있는 결과가 나왔다는 일종의 ‘경고’ 메시지랍니다. 예를 들어, 10 을 3 으로 나누면 3.3333…
하고 끝없이 이어지잖아요? 컴퓨터도 이런 숫자를 표현할 때 한정된 자릿수 때문에 완벽하게 표현하지 못하고 가장 가까운 값으로 ‘어림짐작’해서 표현해요. 이때 발생한 아주 작은 오차를 알려주는 신호라고 이해하시면 돼요.
우리가 흔히 생각하는 ‘버그’나 ‘심각한 오류’라기보다는, 부동소수점 연산의 자연스러운 특성에서 오는 ‘결과가 정확하진 않아’라는 정보에 가깝죠. 제가 개발할 때 이 경고를 만나면 ‘아, 소수점 계산에서 약간의 틈이 생겼구나!’ 하고 인지하는 편이에요.
질문: 그럼 STATUSFLOATINEXACTRESULT는 왜 발생하는 건가요? 제가 코드를 잘못 짜서 그런 건가요?
답변: 아니요, 대부분의 경우 코드를 잘못 짰다기보다는 부동소수점 연산 자체의 특성 때문에 발생하는 경우가 많아요. 우리 컴퓨터는 숫자를 0 과 1 로 이루어진 이진수로 표현하잖아요? 그런데 0.1 이나 0.2 같은 십진수 소수들이 이진수로는 정확하게 표현되지 않는 경우가 많답니다.
마치 1/3 을 십진수로 완벽하게 표현할 수 없어서 0.333… 으로 계속 이어지는 것과 비슷해요. 컴퓨터도 이진수로 0.1 을 표현하려고 하면 끝없이 이어지는 형태가 되고, 결국 중간에서 잘라내어 가장 가까운 값으로 저장하게 되죠. 이러다 보니 0.1 + 0.2 를 계산하면 우리가 기대하는 정확히 0.3 이 아니라 0.29999999999999998 같은 미세한 오차가 발생할 수 있어요.
STATUSFLOATINEXACTRESULT는 바로 이런 ‘이진수 표현의 한계’ 때문에 수학적인 결과와 컴퓨터 계산 결과가 미묘하게 달라졌을 때 나타나는 거랍니다. 그러니까 여러분의 코드가 틀렸다기보다는, 컴퓨터가 숫자를 다루는 방식 때문에 생기는 자연스러운 현상에 가깝다고 보시면 돼요.
질문: STATUSFLOATINEXACTRESULT를 마주쳤을 때, 어떻게 대처해야 할까요? 항상 신경 써야 하는 문제인가요?
답변: 이 질문, 정말 중요해요! 제가 개발하면서 느낀 바로는, ‘언제나 심각하게 받아들여야 하는 건 아니지만, 상황에 따라 다르게 대처해야 한다’가 정답이에요. 예를 들어, 게임 개발처럼 아주 미세한 오차가 사용자 경험에 큰 영향을 주지 않는다면 대부분 무시해도 괜찮아요.
하지만 은행 잔고 계산이나 과학 시뮬레이션처럼 ‘단 한 푼의 오차도 용납할 수 없는’ 정밀한 계산이 필요한 경우에는 이 경고를 절대 무시해서는 안 되죠. 이때는 몇 가지 방법을 고려해볼 수 있어요. 첫째, 더 높은 정밀도를 지원하는 자료형(예: double 대신 long double, 또는 십진수를 직접 다루는 Decimal 타입)을 사용하는 것을 고려해볼 수 있어요.
둘째, 특정 지점에서 반올림이나 버림 같은 명시적인 오차 처리 로직을 추가하여 의도한 대로 결과를 만들어내는 거죠. 셋째, 이 플래그가 설정되었는지 확인하고, 필요하다면 해당 연산을 다시 검토하거나 특수 처리하는 코드를 작성할 수도 있어요. 결국 중요한 건, ‘내 프로그램이 어느 정도의 정밀도를 요구하는가’를 스스로 판단하는 경험이 쌓여야 한다는 점입니다.
저도 처음엔 모든 inexact result 를 두려워했지만, 이제는 ‘이 정도는 괜찮아’와 ‘이건 꼭 잡아야 해!’를 구분하는 노하우가 생겼어요!