ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Zero Division with Floating-Point Numbers
    프로그래밍 언어 2023. 11. 16. 02:04

    개발을 하면서 어떠한 값을 0으로 나누는 미친 짓을 하는 개발자는 없겠지만 (그게 나야) 부동소수점에서의 Zero Division을 알아보고자 한다.

     

    우선 두 가지의 배경 지식이 필요하다. 

    부동 소수점 계산

    첫 번째로 흔한 개발자 상식으로 나오는 문제를 살펴보자. $1.1 + 0.1 == 1.2$는 $true$일까? 아님 $false$일까? 정답은 $false$이다.

    1.1 + 0.1 != 1.2

     

    이는 부동 소숫점을 어떻게 표현하는지에 대해 확인하면 왜 $false$가 나오는지 알 수 있다. float의 경우 부호 $1$비트, 지수 부분 $8$비트, 가수 부분 $23$비트로 구성되고, double의 경우 부호 $1$비트, 지수 부분 $11$비트, 가수 부분 $52$비트로 이루어져있다.

    float와 double 타입의 구조

     

    정수와 다르게 부동 소숫점은 정확한 값으로 표현할 수 없으며 근사값으로 표현되기 때문에 동등 비교 시 $false$가 출력된다.

    double 타입의 부동 소숫점 출력값
    double 타입의 부동 소숫점을 32번째 자리까지 출력한 값

     

    단, float 타입의 경우 정확도가 매우 떨어져 $1.1f + 0.1f == 1.2f$가 $true$를 반환하게 된다. 정확한 소숫점 계산을 위해선 float타입이 아닌 double 타입을 사용하길 권장한다.

    float 타입의 부동 소숫점 동등 비교

    Zero Division

    두 번째로 코딩을 하다 보면 하지 말아야 할 연산 중 자주 마주하는 상황이 있다. 바로 $0$으로 나누는 행위이다. 이를 Zero Division이라고 부르며 이는 프로그래머가 의도하지 않은 값을 출력하여 심각한 버그를 발생시킨다.

    Zero Division with integer-numbers

    부동 소수점의 Zero Division

    그렇다면 부동소수점 형태의 $0$으로 나눈다면 어떻게 될까?

    Zero Division with floating-numbers (INF)

     

    에러가 발생하지 않고 $inf$라는 값이 출력된다. 부동소수점으로 $0$을 정확하게 표현할 수 없어 $0$은 아니지만 $0$과 거의 비슷한 아주 작은 수로 표현해야 하기 때문이다. $1.0f \ / \ 0.0f$는 $0.0f$에 비해 $1.0f$가 굉장히 큰 값이므로 무한대로 발산하기 때문에 $inf$가 출력된다.

     

    그렇다면 $0.0f \ / \ 0.0f$의 값은 무엇일까? $NaN$, 즉 정의할 수 없는 값이 출력된다. $0.0f \ / \ 0.0f$은 어떠한 값으로 수렴하지도 않고 발산하지도 않아 정의할 수 없기 때문에 $NaN$이 출력된다.

    Zero Division with floating-numbers (NaN)

     

    그렇다면, $0.0f$로 나누는 행위가 에러가 아니라면 $1.0f \ / \ 0.0f == 1.0f \ / \ 0.0f$는 $true$일까? $false$일까?

    INF 비교

    $true$가 반환된다. 그렇다면, $0.0f \ / \ 0.0f == 0.0f \ / \ 0.0f$는 $true$일까? $false$일까?

    NaN 비교

    $false$가 반환된다. 이러한 결괏값을 내는 이유를 확인하기 위해선 Visual Studio의 Compiler가 부동 소수점을 어떻게 다루는지에 대해 알아볼 필요가 있다.

     

    Visual Studio의 옵션 중엔 /fp라는 옵션이 존재한다. 이는 Specify floating-point behvaior, 즉 Compiler가 부동 소수점을 어떻게 다루고, 최적화하고, 예외처리하는지에 대한 옵션이며 여러 옵션이 있지만 /fp:precise 옵션이 Default 값이다.

     

    해당 옵션에선 특별한 값들($NaN$, $+infinity$, $-infinity$, $-0.0$)에 대한 비교 연산을 따로 정의하고 있다.

     

    그 중 $NaN$의 경우 정의되있지 않은 값이기 때문에 $NaN$끼리의 동등 비교 연산은 $false$를 반환하고 $+infinity$, $-infinity$, $-0.0$는 동등 비교 연산 시 $true$를 반환한다.

     

    참조 문서 : https://learn.microsoft.com/en-us/cpp/build/reference/fp-specify-floating-point-behavior?view=msvc-170

     

    /fp (Specify floating-point behavior)

    Learn more about: /fp (Specify floating-point behavior)

    learn.microsoft.com

     

    '프로그래밍 언어' 카테고리의 다른 글

    OOP Design Pattern - Structural Pattern  (0) 2024.01.18
    OOP Design Pattern - Creational Pattern  (0) 2024.01.12
    [C++] 이동 의미론 Move Semantics  (0) 2023.11.20
    입실론 테스트  (0) 2023.11.20
    객체 지향 설계 SOLID  (0) 2023.11.16
Designed by Tistory.