<aside>
⚠️ 0.1f + 0.2f == 0.3f가 아닌 이유 정도는 알아야 읽기 수월할지도?
</aside>
IEEE 754는 부동소수점에 대한 표준이다.
저장 방식과 사칙연산, 예외 상황이나 각종 초월함수 등 다양한 작업에 대해 다룬다.
모든 곳에서 반드시 지켜지는 것은 아니다. 지키지 않을 수도 있다.
32비트 단정밀도 float은 부호 1비트/지수부 8비트/가수부 23비트를,
64비트 배정밀도 double은 지수부 11비트/가수부 52비트를 사용한다고 한다.
그래서 혹시 이걸로 왜 1.0f가 0x3F800000인지 설명할 수 있는 분?
부동소수점으로 정확히 어떻게 표현되는지 아는 것을 목표로 간단히 알아보자.
부호있는 정수(signed integer)는 맨 앞 1비트를 부호를 나타내는 데 사용한다.
마찬가지로 부동소수점에서도 맨 앞 1비트를 부호를 나타내는 데 사용한다.
하지만 일반적으로 2의 보수를 사용하는 부호 있는 정수와는 달리,
부동소수점은 1의 보수처럼 부호 비트가 1이라면 단순히 -를 붙여준다.
일부 경우에서 0.0f와 -0.0f가 다르게 취급되는 이유가 이것이다.
int32_t의 경우
0-214748364832비트 float의 경우
0.0f-0.0f어떤 수를 과학적 기수법으로 나타내면 1.BBBeXX 또는 -1.BBBeXX 꼴이 된다.
1. 부분은 공통이므로 생략 (0과 NaN 등의 예외는 후술)XX 부분이 지수부에, BBB 부분이 가수부에 들어가게 된다.예를 들어 십진수 100.625를 이진수로 나타내면 1100100.101가 되고,
과학적 기수법으로 나타내면 1.100100101e6이 된다. (1.100100101 × 2^6)
가수부가 10비트인 16비트 반정밀도의 경우 가수부가 1001001010이 된다.
지수부가 5비트인 16비트 반정밀도의 경우 지수가 1이면 지수부가 10000이 된다.
float의 경우 10000000이 된다.위에서 예로 든 십진수 100.625의 경우, 1.BBBeXX의 XX 부분에 6이 들어간다.
그러므로 십진수 100.625를 16비트 반정밀도로 표현하면 지수부는 10101이 된다.
그래서 십진수 100.625가 16비트로 0101011001001010, 즉 0x5696이 되는 것이다.
0 - 1비트10101 - 5비트1001001010 - 10비트마찬가지로 32비트로는 010000101100100101000000000000000, 즉 0x42C94000
위처럼 간단히 모든 수를 표현할 수 있다면 좋겠지만 해결해야 할 문제가 남았다.
0은 과학적 표기법으로 나타낼 때 1.BBBeXX 꼴이 되지 않아 0을 나타낼 수 없다.
그리고 큰 문제는 아니지만 지수부가 0이 되면 그보다 작은 수를 나타낼 수 없다.
그래서 지수부가 0인 경우 맨 앞이 1.이 아닌 0.으로 봐 두 문제를 모두 해결한다!
NaN, infinity, -infinity지수부의 모든 비트가 1인 경우는 특별한 수를 위해 예약되어 있다.
가수부가 0이면 infinity로 (부호 1비트가 1이면 -infinity), 아니면 NaN으로 본다.
내용이 달라도 0b0_11111_0101010101도 NaN이고 0b0_11111_111111111도 NaN이다.
1.이 아닌 0.으로 시작infinity (부호 비트에 따라 -infinity)NaN부동소수점이 어떻게 저장되는지, 그리고 왜 그렇게 저장되는지까지 간단히 알아봤다. -끝-