본문 바로가기
  • 공부, 여행 리뷰해요~~!!
공부/C++

C++, 부동소수점

by 하나리나 2024. 4. 15.
반응형

패스트캠퍼스 C++ 실력 완성 올인원 패키지 Online 수강 내용 중, 공부한 내용을 올립니다.

(강추입니다..)

C++ 부동소수점

 

1. 부동소수점 이란?

 - 부동소수점은 실수를 표현하는 방법이다.

 - C++에서는 보통 float: 32 bit이며, 이 중 지수부는 8bit, 가수부는 23 bit, 부호부는 1bit를 사용한다.

 - double은 64 bit이며, 지수부 11bit, 가수부 52 bit, 부호부 1bit를 사용한다.

 - long double은 64~128 bit 를 사용한다.

 - 개발환경에 따라 달라지므로 확인이 필수이며, 필요에 따라 bit값을 고정하여 실수를 선언한다.

	float num0 = 1;
	double num1 = 1;
	long double num2 = 1;
	cout << sizeof(num0) << endl;
	cout << sizeof(num1) << endl;
	cout << sizeof(num2) << endl;
	// c++에서 실수는 double이 디폴트임.
	// float이나 long double 이용해서 형변환 하는꼴.
	cout << sizeof(1.0f) << endl;
	cout << sizeof(1.0) << endl;
	cout << sizeof(1.0L) << endl; // Long double
	//하지만 Integer와 마찬가지로 개발환경에 따라 달라짐.

 

2. 부동소수점 예시

 예) -118.625

 - 해당 실수를 이진수로 변환하면, -1110110.101 이 된다.

 - 이것을 10의 제곱수로 표현하면, -1.110110101 10e6 (2)가 된다. 

   *여기서 10e6은 10^(6) 이며, (2)는 binary 라는 뜻이다.

 - -1.110110101 10e(6)의 경우,

   1) 부호부: 1 (음수)

   2) 가수부: 1000 0101

   3) 지수부: 1 1011 0101 

 - 가수부, 지수부를 따져보자.

  *가수부.

   - 가수부의 경우, float 32bit 중 8비트 이다.

   - 0000 0000이 127을 나타내는데, 이는 가수부가 10의 음수 제곱일 경우를 대비해서 이다.

   - 10의 '6' 제곱의 경우, 127+6 = 133이며,

   - 133 to binary = 1000 0101 이다.

  *지수부

   - 지수부는 소수점 숫자 이다.

	unsigned int a;
	float b = -118.625;
	memcpy(&a, &b, sizeof(b)); // b의 값을 a로 카피 한다. 메모리 상의 값을 직접 복사
	cout << a << endl; //a의 값을 binary 로 변환하면, 위에서 구한 값이 됩니다. 
	cout << b << endl;

 

3. 주의 사항

 - 10진수 0.1이나 0.02는 2진수로 표현할 수 없다.

 - 컴퓨터는 가장 근접한 숫자로 이를 표현한다.

	// 주의해야 할 점!! (굉장히 조심해야 함.)
	float num_A = 0.1f;
	float num_B = 0.02f * 5.0f;

	cout << "\n주의" << endl;
	cout << num_A << endl;
	cout << num_B << endl;

	if (num_A == num_B)
		cout << "Equal" << endl;
	else
		cout << "No Equal" << endl;

	cout.precision(64);
	cout << "\n정밀도 확인" << endl;
	cout << num_A << endl;
	cout << num_B << endl;

	if (num_A == num_B)
		cout << "Equal" << endl;
	else
		cout << "No Equal" << endl;

 

 - 이를 대비하기 위해 Epsilon 을 사용할 수 있는데,

   이는 표현 가능한 가장 작은 숫자를 사용하여, 차이값 확인을 통해 숫자가 같은지 비교하는 방법이다.

 - 하지만, Epsilon 은 사용할 때마다 오차가 누적되므로, 이 또한 주의가 필요하다.

	float testA = 1.0f;
	float testB = 0.0f;
	for (int i = 0; i < 1000; i++) 
	{
		testB = testB + 0.001;
	}
	if (testA == testB) 
		cout << "equal, 1.0f = 0.001 * 1000" << endl;

 

4. float의 최대값을 구해보자.

 - 아래와 같이 생긴 것이 float의 최대값이라고 예상할 수 있다.

 - 하지만 값이 이상하다. 

 - 지수부가 다 1이면 not a number 이기 때문이다.

	unsigned int flt_max = 0b01111111111111111111111111111111;
	float flx_max_tmp;
	memcpy(&flx_max_tmp, &flt_max, sizeof(flt_max));
	cout << flx_max_tmp << endl; //값이 이상함. 
	// 지수부가 다 1이면 Not A Number 임.
	// 지수부에서 1을 빼야함.

 

- 지수부가 11111110인 것이 float의 최대값이다.

	unsigned int flt_max2 = 0b01111111011111111111111111111111;
	float flx_max_tmp2;
	memcpy(&flx_max_tmp2, &flt_max2, sizeof(flt_max2));
	cout << flx_max_tmp2 << endl; // 최대값

 

5. 무한대의 표현

 - 지수부가 다 1이고, 가수부가 다 0이면 무한대 이다.

	unsigned int flt_max3 = 0b01111111100000000000000000000000;
	float flx_max_tmp3;
	memcpy(&flx_max_tmp3, &flt_max3, sizeof(flt_max3));
	cout << flx_max_tmp3 << endl;
반응형