그 놈의 부동소수점, 한 번에 끝내자.

Nitroblue 1·2025년 9월 29일

자료구조

목록 보기
5/15

Data Basics

부동소수점

-1^sign x (1.mantissa) x 2^(exponent-bias)
-> 즉, 부호 + 가수(Mantissa) = 지수(Exponent)로 표현한다.

float (32bits)

1 bit : sign
8 bits : exponent, bias=127
23 bits : mantissa, 숨겨진 1 포함하면 24비트 정밀도

ex) 0100_0001_0011_0000_0000_0000_0000_0000 -> 총 32비트

  • sign : 0 -> 양수
  • exponent : 1000_0010 (130) -> 실제 지수 = 130 - 127(bias) = 3
  • mantissa : [1.]011 -> 앞에 [1.]은 원래 붙어있음. why? IEEE 754에서는 정규화 수를 쓰기 때문에, 가수부는 항상 1.xxx꼴로 나타낸다. 따라서 앞의 1.은 hidden bit로 간주.
    • 1 x 2^0 + 0 x 2^(-1) + 1 x 2^(-2) + 1 x 2^(-3) = 1 + 3/8 = 1.375

따라서 최종값은 (-1)^0 1.375 2^3 = 11 이다.

그러므로 이 float의 max, min을 계산해보면
부호가 음수, 지수 8bits가 전부 1, mantissa도 전부 1이면 될 것이다.
즉, 1111_1111_1111_1111_1111_1111_1111_1111

하지만! IEEE 754에는 특수 규칙이 있다.
위처럼 exponenet bit가 전부 1이어서 255가 되고, mantissa가 0이 아니면 Not a number를 위한 예약값을 지칭하게 된다.

이처럼 IEEE 754에는 이런 예외 규칙들이 있다.
exponent = 0, mantissa = 0 -> +-0
exponent = 0, mamtissa != 0 -> Denormalized number
exponent = 255, mantissa = 0 -> 무한대
exponent = 255, mantissa != 0 -> NaN

그러므로 최대절댓값은 0111_1111_0111_1111_1111_1111_1111_1111 이다.

  • sign : 0 -> 양수
  • expo : 1111_1110 (255 바로 직전 값인 254) -> 254 - 127 = 127
  • mant : 1.1111 ... ~= 1.99999988
    => (1.111...)2 x 2^127 = 3.4028235... x 10^38

최소절댓값은 0000_0000_0000_0000_0000_0000_000_0001 이다.

  • sign : 0 -> 양수
  • expo : 0000_0000 (0) -> 0 - 127 = -127 No!!!! just -126
  • mantissa : 0000_...0001 -> 0 + 2^(-23)
    exponent가 전부 0이면 'Denormalized number'로 불리며, 이 때는 Mantissa 영역의 1.~으로 약속했던 hidden bit를 0으로 생각한다. 따라서 0.~~
    또한, exponent가 0이라 해서 0 - 127 = -127이 아니라, -126으로 고정한다.
    이렇게 예외를 만든 이유는 Gradual Underflow를 보장하기 위해서. 이 영역덕분에 0까지 부드럽게 이어서 내려갈 수 있다.

그래서 float의 최소절댓값은 4.94.. 10^-324, 최대절댓값은 1.7977.. 10^308 이다.
double은 float과 완전 동일한 구조를 가지며, sign, exponent, mantissa/fraction 파트의 비트 분배와 지수 파트의 bias값만 달라질 뿐이다.

  • sign 1 bit / exponent 11 bits, bias = 1023 / mantissa 52 bits

0개의 댓글