[C++] 부동 소수점
이 글은 패스트캠퍼스 C++ 실력 완성 올인원 패키지 Online.를 보고 따라 만들면서 헷갈리는 부분을 정리한 글입니다.
부동 소수점 자료형
int가 정수형을 저장하는 자료형이라면 소수점을 저장하는 변수는 float
, double
, long double
등이 있다.
부동 소수점 선언
#include <iostream>
using namespace std;
int main()
{
float f = 1.0;
double d = 1.0;
long double ld = 1.0;
cout << sizeof(f) << endl; // 4
cout << sizeof(d) << endl; // 8
cout << sizeof(ld) << endl; // 8
}
부동 소수점의 값은 뒤에 어떤 문자를 붙이냐에 따라 float, double, long double인지 정해진다.
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
cout << typeid(1.0f).name() << endl; // float (f를 붙임)
cout << typeid(1.0).name() << endl; // double(안붙임)
cout << typeid(1.0L).name() << endl; // long double(L을 붙임)
}
부동 소수점 주의해야할 점
오차가 작은 수의 비교
다음 예시를 보면 언뜻 눈으로 보기에는 두 값이 같아보이지만 비교해보면 두 값이 다르다고 나온다.
#include <iostream>
using namespace std;
int main()
{
float num0 = 0.1f;
float num1 = 0.02f * 5.0f;
if (num0 == num1)
cout << "두 값은 같다." << endl; // X
else
cout << "두 값은 틀리다." << endl; // 여기가 출력됨
}
이는 사실 두 값인 num0과 num1를 자세하게 출력해보면 알 수 있다.
float num0 = 0.1f;
float num1 = 0.02f * 5.0f;
cout.precision(64);
cout << num0 << endl;
cout << num1 << endl;
사실 0.1이라는 숫자를 정확히 표현할 수 없어서 매우 유사한 값을 대입하기 때문에 비교했을 때 두 값이 같지 않은 상황이 발생한다.
자료형이 다른 부동소수점의 비교
또 다른 예시로는 다음과 같은 예시가 있다.
다음 예시는 부동소수점 자료형이 다르기 때문에 두 값이 같지 않다고
된다.
#include <iostream>
using namespace std;
int main()
{
float num0 = 0.1f;
if (num0 == 0.1)
cout << "0.1과 같다." << endl; // X
if (num0 == 0.1f)
cout << "0.1f과 같다." << endl; // O
if (num0 == 0.1L)
cout << "0.1L과 같다." << endl; // X
}
매우 매우 작은 수와의 계산
인식하지 못할 정도의 작은 수와 함께 계산할 경우 아예 먹힐 수가 있다.
#include <iostream>
using namespace std;
int main()
{
float num0 = 1.0f;
// float 앱실론 보다 작은 값 (앱실론 -> 부동 소수점의 가장 작은 간격)
unsigned int num1 = 0b00110011100000000000000000000000;
float num2;
memcpy(&num2, &num1, sizeof(num1));
cout.precision(64);
cout << num0 + num2; // num2가 먹혀서 그냥 1로 출력됨
// 0011,1111,1000,0000,0000,0000,0000,0000 = 1.0(2)
// 0011,0011,1000,0000,0000,0000,0000,0000 = 1.0(2) * (10^ -24)
}
// 출력 결과
// 1
큰 수와의 덧셈
또 한 반대로 큰 숫자와 계산할 때도 숫자가 먹힐 수 있다.
#include <iostream>
using namespace std;
int main()
{
float num0 = 1.0f;
// float 앱실론 보다 작은 값 (앱실론 -> 부동 소수점의 가장 작은 간격)
unsigned int num1 = 0b01001011100000000000000000000000;
float num2;
memcpy(&num2, &num1, sizeof(num1));
cout.precision(64);
cout << num2 << endl; // 16777216
cout << num0 + num2; // 16777216 (1이 먹혀서 사라짐)
// 0011,1111,1000,0000,0000,0000,0000,0000 = 1.0(2)
// 0100,1011,1000,0000,0000,0000,0000,0000 = 1.0(2) * (10^ 24)
}
// 출력 결과
//16777216
//16777216
댓글남기기