IEEE 754 부동 소수점 관련 간단한 정리.
카테고리: Cpp
태그: Hobby
IEEE754 부동소수점
부동 소수점의 구성.
- 부호부 : 최상위 1비트(양수, 음수 판별)
- 지수부 : 부호부 다음 8비트
- 가수부 : 지수부 다음 23비트
-38.625를 이진법으로 변환한다.
-38.625를 이진법으로 변환한다.
- 처음 부호부는 -38.625가 음수이니 1을 넣어준다.
- 38.625에 대한 이진 수 변환처리를 해보면 100110.101이 된다.
- 소수점을 왼쪽으로 이동시켜 정수부가 한 자리가 되도록 만든다.
따라서 100110.101 → 1.00110101이 된다.
- 3번에서 왼쪽으로 몇 번 이동했는가? 5번 이동했다. 이동한 자릿수만큼을 2의 지수로 하여 곱해준다.
따라서 1.00110101 * 2^5가 되며, 이를 정규화 된 부동 소수점이라고 한다.
- 지금껏 계산했던 소수점 아래 부분(0011 0101)이 가수부(23비트)가 되도록 나머지 비트를 0으로 채운다. (0011 0101 0000 0000 0000 000 * 2^5) ← 이걸 가수부라고 한다.
- 32bit IEEE754에는 Bias라는 게 있다. 이건 127 값이며, 우리는 위에서 곱한 2의 지수(5)를 더해서 이를 이진수로 변환한다 (127 + 5 == 132 → 1000 0100) ← 이게 지수부(8비트)이다.
- 이걸 조합하면 1(부호부) 1000 0100(지수부) 0011 0101 0000 0000 0000 000(가수부)가 된다.
float을 int로 conversion할 때 일어나는 일.
std::cout << "static_cast<int>(52.6f) = " << static_cast<int>(52.6f) << std::endl;
std::cout << "static_cast<int>(-74.3f) = " << static_cast<int>(-74.3f) << std::endl;\
//static_cast<int>(52.6f) = 52
//static_cast<int>(-74.3f) = -74
- 여기서 알아야 할 것은 내림이 아니라, 버리는 것이다.
일어날 수 있는 문제점
- 정밀도 손실 → float값에 소수점 이하 부분이 포함되어 있을 경우, int로 변환할 시에 소수점 이하가 버려져서 원래 값의 일부 정보가 손실될 수 있다.
- 범위 초과(오버 플로우) → float가 표현할 수 있는 값의 범위는 int의 범위와 다르다. 따라서 float값이 담고있는 범위가 int와 다를 때, 결과가 정의되지 않거나 예기지 못한 값이 나올 수 있다.
float aa = 321321354132132.23;
cout << aa << endl;
cout << static_cast<int>(aa);
//3.21321e+14
//-2147483648
- 위에서 서술했듯이, float을 int로 형변환 할 때는 기본적으로 소수점 이하를 버림(내림이 아님) 처리한다. 따라서 반올림을 기대하는 경우에는 별도의 처리가 필요하다.
이 부작용을 줄이기 위한 방법
- 범위 검사 → int형이 표현할 수 있는 범위인가? 먼저 검사해서 예외처리
- 반올림이 필요할 경우(rount, floor, ceil)과 같은 함수를 사용한다.
#include <cmath>
float f = 9.99f;
int i = static_cast<int>(std::round(f)); // 올바른 반올림 처리 후 변환
- 암시적 형변환이 아닌 명시적 형변환을 통해 암시적 형변환의 예기치 못한 부작용 방지.
댓글 남기기