C++ Chapter 2.4 : 부동소수점수 floating point numbers

Date:     Updated:

카테고리:

태그:

인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!


Chapter2. 변수와 기본 자료형

부동소수점수

영역 데이터 형 최소 크기 전형적인 크기
부동소수점 float 4byte 4byte
부동소수점 double 8byte 8byte
부동소수점 long double 8byte 8 or 12 or 16 byte


float의 내부

Q. 0000011111000000000000000000000 이 이진수를 float 실수로 어떤 수인지 알아보자

\[0 \ \ 0000111\ \ 11000000000000000000000 = +1.313554 \ * 10^{-36}\]
  • float
    • 4 byte = 32bits = 총 32자리
  • 부호 비트
    • 1자리
    • 0 이므로 +양수이다.
\[00000111 = 2^0 +2^1+2^2=7\]
  • 지수 비트
    • 8자리
    • 00000111
    • 십진수로 7 이다.
\[11000000000000000000000=2^{-1}+2^{-2}=0.5 +0.25 = 0.75\]
  • 가수 비트
    • 23자리
    • 왼쪽 앞부터 (2^-1) 이며 소수 자리를 나타낸다.
      • -1, -2, -3, -4, …. 순
    • 십진수로 0.75이다.


\[+(1+0.75)\ * \ 2^{(7-127)} = +1.313554 \ * 10^{-36}\]
  • +
  • ( 1 + 0.75 )
    • 가수 비트 십진수 값에 1 더해주기
  • 2^(7-127)
    • 지수 비트 십진수 값에 127을 빼주는 이유는 32bit 기준으로 메모리에 값을 저장할 때 따르는 규칙이라고 보면 된다.
  • + ( 1 + 0.75 ) * 2^(7-127) 을 계산한 값이 +1.313554 * 10^{-36} 가 된다.


std::numeric_limits<타입>::lowest()

  • min : 가장 작은 절대값
  • lowest : 가장 작은 값. 음수일 수도.
  • 각각 float, double, long double 이 표현할 수 있는 범위 중에서 가장 작은 값을 리턴해준다.

image


실수의 다양한 표현 방법

  • float f(3.14)
    • double형인 3.14를 float으로 자동으로 형 변환해주어 저장한다. C++에서만 가능.
    • float f{3.14} 대괄호 사용은 엄격하여 형변환 불가능
\[e-1 = *10^{-1}, \ e2 =*10^2\]
float f(3.14) 

cout << 3.14 << endl;
cout << 31.4e-1 << endl; // 3.14 출력
cout << 31.4e-2 << endl; // 0.314 출력
cout << 31.4e1 << endl; // 3.14 출력
cout << 31.4e2 << endl; // 3.14 출력


std::setprecision(n)

  • #include <iomanip>
    • 입출력 조작하는 라이브러리
  • 자리 수를 지정한다.

ex1)

cout << setprecision(16) << endl;
cout << 1.0 / 3.0 << endl;
  • cout « setprecision(16) « endl;
    • 출력 스트림에 16자리까지 보장하도록 정보를 보낸다.
  • cout « 1.0 / 3.0 « endl;
    • 평소같으면 0.333333 이 정도 자리수의 정밀도만 보장할텐데
    • setprecision(16)으로 16자리까지 꼭 출력하도록 됐기 때문에
    • 0.3333333333333333 출력

정밀도 차이가 쌓이소 쌍이면 버그나 잡기 힘든 에러가 생길 수 있다

  • 실수 표현의 원리
    • 이진수로 만드는거기 때문에 최대한 가깝게 표현하는 것이다.
    • 0.25 처럼 2^(-2)로 딱 떨어지는 이진수 소수라면 100% 정확하지만
    • 0.1 처럼 십진수 소수라면 그냥 이진수의 합의 조합들로 최대한 0.1에 가깝게 만드는 것이다.
    • 그러므로 정확한 값과 차이가 존재한다.
    • 정밀도가 높을 수록 최대한 가깝게 만들어 보는 것.

ex2)

double d(0.1);

cout << d << endl;
cout << std::setprecision(17);
cout << d << endl ; 
  • cout « d « endl;
    • 0.1 출력
      • 사실 딱 떨어지는 0.1이 아니고 내부적으로 최대한 0.1에 가깝게 만든 것이다.
  • cout « std::setprecision(17);
    • 출력 스트림에 16자리까지 보장하도록 정보를 보낸다.
  • cout « d « endl ;
    • 0.1000000000000001
    • 17자리로 출력하니 안보이던 끝에 1이 보인다.
    • 실제론 17자리 그 이상이였던 것 !!!!!!!!!!!!!!!!!!!!!!!!!!
    • 이렇게 이진수들의 합으로 십진수인 0.1에 최대한 가깝게 만든 것!

ex3)

double d1(1.0);
double d2(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1);

cout << std::setprecision(17);
cout << d1 << endl;
cout << d2 << endl;
  • cout « d1 « endl;
    • 1 출력
    • 17자리까지 안간다. 그냥 딱 떨어진 1 한자리 출력
    • 1은 2의 0승이기 때문에 이진수로 표현이 깔끔하게 가능하기 때문이다.
    • 실제로 딱 1 한자리
  • cout « d2 « endl;
    • 0.99999999999999999
    • 1.0이 아닌 0.99999999999999999 로 나오는 이유
      • 각각 더해주는 0.1를 이진수로 표현을 먼저 한 후 더해주기 때문이다.
      • 이진수로 0.1은 딱 떨어지는 수가 아니기 때문에 이진수로 최대한 표현하다보니 차이가 생기는 것.
      • 이들을 다 더하니 1.0에 가까워지긴 했지만 딱 떨어지는 1.0은 아니다.


🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기

댓글남기기