• 2.4.1 부동소수점수(floating point numbers) 종류
  • 2.4.2 limits 헤더를 이용한 부동소수점수 한계치 확인
  • 2.4.3 과학적 표기법(scientific notation)
  • 2.4.4 Floating error
  • 2.4.5 inf and nan

2.4.1 부동소수점수(floating point numbers) 종류

 

부동소수점수는 float, double, long double로 총 3가지가 c++에 존재한다. 부동소수점이라고 불리는 이유는 과학적 표기법(scientific notation)에 의해 주어진 수의 소수점 위치가 이동하기 때문이며, 부동은 움직이지 않는다는 의미가 아닌 떠다닌다의 의미로 받아들이면 된다.

 

float 자료형은 딥러닝에서 자주 쓰고 기본 실수 계산은 double을 선호하게 된다. 딥러닝이 아닌 일반 수치해석적 과학 계산에서는 double을 사용하는 것을 선호한다.

 

float-point numbers(32 bit)

 

float-point numbers(64 bit)

 

부동소수점수는 부호와 지수, 가수를 통해 구현이 된다. 이러한 표현 방식 때문에 실제 값과 입력 값 차이의 오차가 생기는 한계가 생긴다.


2.4.2 limits 헤더를 이용한 부동소수점수 한계치 확인

 

sizeof 연산자를 이용하면 각 자료형에 대한 크기를 알 수 있다. 이전과 동일하게 limits 헤더를 이용하면 해당 자료형의 한계치를 확인할 수 있다. lowest 함수를 사용해야 가장 작은 음수를 확인할 수 있다.

 

#include <iostream>
#include <limits>

int main()
{
	using namespace std;

	cout << sizeof(float)			<< endl; // 4 bytes
	cout << sizeof(double)		<< endl; // 8 bytes
	cout << sizeof(long double)	<< endl; // 8 bytes

	cout << numeric_limits<float>::max()		<< endl; // min() lowest()
	cout << numeric_limits<double>::max()		<< endl;
	cout << numeric_limits<long double>::max()	<< endl;

	return 0;
}

2.4.3 과학적 표기법(scientific notation)

 

지수 표현을 활용하여 과학적 표기법을 쓸 수 있다. 지수 표현의 경우 과학 계산에서 상수로 쓸만한 값들에 대해 쓰는 것 이외에는 볼 수가 없지만 실무에서의 규칙은 모든 회사가 다르기 때문에 그에 맞게 사용하면 된다.

 

#include <iostream>

int main()
{
	using namespace std;

	// scientific notation
	cout << 3.14		<< endl;
	cout << 31.4e-1	<< endl;
	cout << 31.4e-2	<< endl;
	cout << 31.4e1		<< endl;
	cout << 31.4e2		<< endl;

	return 0;
}

 

e-1은 1/10을 의미하며, e-2은 1/100을 의미한다. +에 대해서는 역수를 취하면 된다. 또한 +는 생략이 가능하다.


2.4.4 Floating error

 

float 자료형이 아닌 double 자료형도 흔히 사용하는 이유는 바로 floating error 때문이다. 메모리를 많이 사용하면 더 세밀한 실수를 다룰 수 있는데, float 자료형을 쓸 경우 소수점 아래 6번째 자리부터 신뢰하기 힘들어진다. double 자료형도 소수점 아래 16번째 자리부터 신뢰하기 힘들어지는데 일반적으로 10자리를 넘어가는 자리수에 대해서는 고려하지 않는다. 또한 콘솔 창에서 표기된 수는 setprecision으로 정확히 보는 게 아닌 이상 믿을 수 없다.

 

#include <iostream>
#include <iomanip> // 입출력 조작

int main()
{
	using namespace std;

	cout << std::setprecision(25);
	cout << 1.0f / 3.0f	<< endl;
	cout << 1.0 / 3.0	<< endl;

	float f1 = 123456789.0f; // 10 significant digits
	cout << f1 << endl;

	double d1 = 1.0;
	cout << d1 << endl;
	cout << std::setprecision(30);
	cout << d1 << endl;

	double d2 = 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1;
	cout << d2 << endl;

	return 0;
}

 

위의 코드를 실행하면 여러가지 의미 있는 결과들을 볼 수 있다. 특히 d1과 d2의 결과는 기억해둘 필요가 있다.


2.4.5 inf and nan

 

0으로 나누는 것을 수학에서 정의하지 않지만 코드를 작성하면서 간혹 0으로 나누는 일을 수행할 수 있다. 0으로 나누는 경우 그 수는 inf로 표기되는데, 무한대라고 보면 된다. 또한 수가 아닌 경우엔 not a number의 약자인 nan으로 표기된다. cmath 헤더에는 인자로 들어오는 수가 inf인지 nan인지 체크해주는 함수가 있다.

 

#include <iostream>
#include <cmath>

int main()
{
	using namespace std;

	double zero	= 0.0;
	double posinf	= 5.0 / zero;
	double neginf	= -5.0 / zero;
	double nan	= zero / zero;

	cout << posinf	<< endl;
	cout << neginf	<< endl;
	cout << nan	<< endl; // -nan(ind) indeterminate
	cout << posinf	<< " " << std::isinf(posinf) << endl;
	cout << neginf	<< " " << std::isinf(neginf) << endl;
	cout << nan	<< " " << std::isnan(nan) << endl;
	cout << 1.0	<< " " << std::isnan(1.0) << endl;

	return 0;
}

'Programming Language > C++' 카테고리의 다른 글

Section 2.6. char 자료형  (0) 2021.10.18
Section 2.5. Boolean 자료형  (0) 2021.10.15
Section 2.3. void  (0) 2021.10.12
Section 2.2. 정수형  (0) 2021.10.11
Section 2.1. 기본 자료형  (0) 2021.09.29

+ Recent posts