부동소수점은 실수를 표현하는 방법 중 하나로, 소수점의 위치를 고정시키지 않고 지수부와 가수부로 나누어 표현합니다. 이를 통해 매우 큰 수나 매우 작은 수를 효율적으로 표현할 수 있습니다.
타입 지정자 | 크기 (비트) | 지수부 (비트) | 가수부 (비트) |
---|---|---|---|
float | 32 | 8 | 23 |
double | 64 | 11 | 52 |
long double | 64 ~ 128 | - | - |
부동소수점 수는 부호, 지수부, 가수부로 구성됩니다.
예를 들어, -118.625를 부동소수점으로 표현하면 다음과 같습니다:
#include <iostream>
#include <cfloat>
#include <cstring> // memcpy를 사용하기 위해 필요
using namespace std;
int main()
{
{
// 부동소수점의 기본 연산
float num0 = 1.5f;
float num1 = num0 * 1.5f;
float num2 = num0 / 2.0f;
float num3 = num0 - 3.0f;
cout << "num0: " << num0 << endl; // 1.5
cout << "num1: " << num1 << endl; // 2.25
cout << "num2: " << num2 << endl; // 0.75
cout << "num3: " << num3 << endl; // -1.5
}
{
// 부동소수점 자료형의 크기
float fnum = 1.0f;
double dnum = 1.0;
long double ldnum = 1.0;
cout << "float: " << sizeof(fnum) << " bytes" << endl; // 4
cout << "double: " << sizeof(dnum) << " bytes" << endl; // 8
cout << "long double: " << sizeof(ldnum) << " bytes" << endl; // 8
cout << "sizeof(1.0f): " << sizeof(1.0f) << " bytes" << endl; // float
cout << "sizeof(1.0): " << sizeof(1.0) << " bytes" << endl; // double
cout << "sizeof(1.0L): " << sizeof(1.0L) << " bytes" << endl; // long double
}
// 정밀도 변경
cout.precision(64);
{
// 부동소수점의 메모리 상의 표현
unsigned int uintNum;
float fnum = -118.625f;
memcpy(&uintNum, &fnum, sizeof(fnum));
cout << "Memory representation of -118.625f: " << uintNum << endl; // 3270328320
cout << "Value: " << fnum << endl; // -118.625
fnum = 0.231689453125f;
memcpy(&uintNum, &fnum, sizeof(fnum));
cout << "Memory representation of 0.231689453125f: " << uintNum << endl; // 1047347200
cout << "Value: " << fnum << endl; // 0.231689453125
}
{
// 부동소수점 비교 연산의 문제점
float num0 = 0.1f;
float num1 = 0.02f * 5.0f;
if (num0 == num1)
cout << "Equal 1" << endl; // 실행 안 됨
if (num0 == 0.1f)
cout << "Equal 2" << endl; // 실행 됨
if (num0 == 0.1)
cout << "Equal 3" << endl; // 실행 안 됨
if (num0 == 0.1L)
cout << "Equal 4" << endl; // 실행 안 됨
cout << "num0: " << num0 << endl; // 0.1 아님
cout << "num1: " << num1 << endl; // 0.1 아님
cout << "0.1f: " << 0.1f << endl;
cout << "0.1: " << 0.1 << endl;
cout << "0.1L: " << 0.1L << endl;
num0 = 1.0f;
num1 = 0.0f;
for (int i = 0; i < 1000; i++)
num1 = num1 + 0.001f;
if (num0 == num1)
cout << "Equal 0" << endl; // 실행 안 됨
if (fabsf(num0 - num1) <= FLT_EPSILON)
cout << "Equal 1" << endl; // 실행 안 됨
num0 = 1.0f;
num1 = 0.0f;
for (int i = 0; i < 10; i++)
num1 = num1 + 0.1f;
if (num0 == num1)
cout << "Equal 2" << endl; // 실행 안 됨
if (fabsf(num0 - num1) <= FLT_EPSILON)
cout << "Equal 3" << endl; // 실행 됨
}
{
// Epsilon 유도
unsigned int intNum0 = 0b00111111100000000000000000000000;
float fNum0;
memcpy(&fNum0, &intNum0, sizeof(intNum0));
cout << "fNum0: " << fNum0 << endl; // 1.0f
unsigned int intNum1 = 0b00111111100000000000000000000001;
float fNum1;
memcpy(&fNum1, &intNum1, sizeof(intNum1));
cout << "fNum1: " << fNum1 << endl; // 1.00000011920928955078125f
float epsilon = fNum1 - fNum0;
cout << "Epsilon: " << epsilon << endl;
cout << "FLT_EPSILON: " << FLT_EPSILON << endl;
}
{
// 1.0f에서 더할 수 있는 가장 작은 수 구하기
float fNum0 = 1.0f;
float fNum1;
unsigned int intNum1 = 0b00110100000000000000000000000000;
memcpy(&fNum1, &intNum1, sizeof(intNum1)); // Epsilon
cout << "fNum0: " << fNum0 << endl;
cout << "fNum1 (Epsilon): " << fNum1 << endl;
cout << "fNum0 + fNum1: " << fNum0 + fNum1 << endl; // 더한 값 출력
}
{
// 1.0f에서 더할 수 있는 가장 작은 수보다 더 작은 수를 더 할 때
float fNum0 = 1.0f;
float fNum1;
unsigned int intNum1 = 0b00110011100000000000000000000000;
memcpy(&fNum1, &intNum1, sizeof(intNum1)); // 매우 작은 수
cout << "fNum0: " << fNum0 << endl;
cout << "fNum1: " << fNum1 << endl;
cout << "fNum0 + fNum1: " << fNum0 + fNum1 << endl; // 더한 값이 나오지 않음
}
{
// 1.0f를 더했을 때 문제가 없이 더해지는 수
float fNum0 = 1.0f;
float fNum1;
unsigned int intNum1 = 0b01001011000000000000000000000000;
memcpy(&fNum1, &intNum1, sizeof(intNum1)); // 큰 수
cout << "fNum0: " << fNum0 << endl;
cout << "fNum1: " << fNum1 << endl;
cout << "fNum0 + fNum1: " << fNum0 + fNum1 << endl; // 더한 값 출력
}
{
// 1.0f를 더했
을 때 더해지지 않는 수
float fNum0 = 1.0f;
float fNum1;
unsigned int intNum1 = 0b01001011100000000000000000000000;
memcpy(&fNum1, &intNum1, sizeof(intNum1)); // 매우 큰 수
cout << "fNum0: " << fNum0 << endl;
cout << "fNum1: " << fNum1 << endl;
cout << "fNum0 + fNum1: " << fNum0 + fNum1 << endl; // 더한 값이 나오지 않음
}
{
// 최대값 구하기
float fnum;
unsigned int uintNum = 0b01111111011111111111111111111111;
memcpy(&fnum, &uintNum, sizeof(uintNum));
cout << "FLT_MAX: " << FLT_MAX << endl;
cout << "fnum (max): " << fnum << endl;
}
{
// NaN 구하기
float fnum;
unsigned int uintNum = 0b01111111111111111111111111111111;
memcpy(&fnum, &uintNum, sizeof(uintNum));
cout << "fnum (NaN): " << fnum << endl;
}
{
// 무한대 구하기
float fnum;
unsigned int uintNum = 0b01111111100000000000000000000000;
memcpy(&fnum, &uintNum, sizeof(uintNum));
cout << "fnum (infinity): " << fnum << endl;
}
{
// TRUE_MIN
float fnum;
unsigned int uintNum = 0b00000000000000000000000000000001;
memcpy(&fnum, &uintNum, sizeof(uintNum));
cout << "FLT_TRUE_MIN: " << FLT_TRUE_MIN << endl;
cout << "fnum (true min): " << fnum << endl;
}
{
// MIN
float fnum;
unsigned int uintNum = 0b00000000100000000000000000000000;
memcpy(&fnum, &uintNum, sizeof(uintNum));
cout << "FLT_MIN: " << FLT_MIN << endl;
cout << "fnum (min): " << fnum << endl;
}
}
부동소수점의 기본 연산:
부동소수점 자료형의 크기:
float
, double
, long double
자료형의 크기를 확인합니다.1.0f
, 1.0
, 1.0L
).부동소수점의 메모리 상의 표현:
memcpy
를 사용하여 부동소수점 값을 메모리에서 정수로 변환해 출력합니다.부동소수점 비교 연산의 문제점:
Epsilon 유도:
부동소수점의 최대값, NaN, 무한대, 최소값: