C++ Chapter 2.4 : 부동소수점수 floating point numbers
카테고리: Cpp
태그: Cpp Programming
인프런에 있는 홍정모 교수님의 홍정모의 따라 하며 배우는 C++ 강의를 듣고 정리한 필기입니다. 😀
🌜 [홍정모의 따라 하며 배우는 C++]강의 들으러 가기!
Chapter2. 변수와 기본 자료형
부동소수점수
영역 | 데이터 형 | 최소 크기 | 전형적인 크기 |
---|---|---|---|
부동소수점 | float | 4byte | 4byte |
부동소수점 | double | 8byte | 8byte |
부동소수점 | long double | 8byte | 8 or 12 or 16 byte |
float의 내부
Q. 0000011111000000000000000000000
이 이진수를 float 실수로 어떤 수인지 알아보자
float
- 4 byte = 32bits = 총 32자리
부호 비트
- 1자리
- 0 이므로 +양수이다.
지수 비트
- 8자리
- 00000111
- 십진수로 7 이다.
가수 비트
- 23자리
- 왼쪽 앞부터 (2^-1) 이며 소수 자리를 나타낸다.
- -1, -2, -3, -4, …. 순
- 십진수로 0.75이다.
+
( 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 이 표현할 수 있는 범위 중에서 가장 작은 값을 리턴해준다.
실수의 다양한 표현 방법
- float f(3.14)
- double형인 3.14를 float으로 자동으로 형 변환해주어 저장한다. C++에서만 가능.
- float f{3.14} 대괄호 사용은 엄격하여 형변환 불가능
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에 가깝게 만든 것이다.
- 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은 아니다.
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글 남기기