C++/Syntax
2021. 3. 9. 19:36
소수점 (Decimal Point)
고정 소수점 (정수)
부호화 절대치
- 맨 왼쪽 비트가 부호를 결정하고, 나머지 비트는 일반 양수를 다루듯 계산한다.
000 -> +0 001 -> +1 010 -> +2 011 -> +3 100 -> -0 101 -> -1 110 -> -2 111 -> -3
안쓰는 이유
순환성이 떨어진다.(+3 다음이 -0)
보수를 사용하면 감산기 없이 가산기만으로 뺄셈이 가능하다.
1의 보수
비트를 반전시켜 순환성을 가지도록 했다.(+3 다음이 -3)
덧셈기로 뺄셈이 가능하다.
000 -> +0 001 -> +1 010 -> +2 011 -> +3 100 -> -3 101 -> -2 110 -> -1 111 -> -0
2의 보수
1의 보수를 취하고 1을 더하는 형태이다.
-0을 없애고 숫자를 하나 더 챙겼다.
빨리 만드는 방법
- 오른쪽부터 왼쪽 방향으로 1을 만날 때까지 그대로, 그 이후는 반전시키면 된다.
000 -> +0 001 -> +1 010 -> +2 011 -> +3 100 -> -4 101 -> -3 110 -> -2 111 -> -1
부동 소수점(실수)
부호 비트, 지수부, 가수부로 구성된다.
single-precision(float) : 지수부(8비트), 가수부(23비트)
double-precision(double) : 지수부(11비트), 가수부(52비트)
(-1)^(부호비트) * (1.(가수부)) * 2^(지수부 - 127)
의 값을 가진다.double-precision의 경우
127(0b01111111)
이 아닌1023(0b01111111111)
참고
- 이기적 유튜브 : 설명이 상당히 꼼꼼하다.
출력 시 precision 조절하기
double d(0.1); std::cout << std::setprecision(16); std::cout << d << std::endl; // 0.10000000000000001
오차는 부동 소수점의 한계이다.
double d(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1); std::cout << std::setprecision(16); std::cout << d << std::endl; // 0.99999999999999989
0으로 나누는 등 수학적인 오류가 발생할 가능성이 있는 경우
실수를 0으로 나누면
inf
이다.0을 0으로 나누면
nan
이다.<cmath>
라이브러리의std::isinf
,std::isnan
으로 체크해야 한다.
float vs double
의외로 연산 속도는 별 차이가 없다.
메모리가 중요하다면
float
, 정밀도가 중요하다면double
을 사용하는게 좋을 듯 하다.오차 예제
#include <iostream> #include <iomanip> int main() { using namespace std; const float f_begin = 1e9f; float f = f_begin; cout << setprecision(10000); cout << f << endl; // 1000000000 for (long long i = 0; i < 1e6; ++i) f += +1e0f; cout << f << "\n\n"; // 1000000000 const double d_begin = 1e9f; double d = d_begin; cout << d << endl; // 1000000000 for (long long i = 0; i < 1e6; ++i) d += +1e0; cout << d << endl; // 1001000000 }
근본적인 해결은 아니지만 임시로 해결하는 방법
작은 연산은 따로 수행한 뒤 한번에 합치는 식으로 하면 된다.
#include <iostream> #include <iomanip> int main() { using namespace std; const float f_begin = 1e9f; float f = f_begin; cout << setprecision(10000); cout << f << endl; // 1000000000 float f2 = 0.0f; for (long long i = 0; i < 1e6; ++i) f2 += +1e0f; f += f2; cout << f << "\n\n"; // 1001000000 }
'C++ > Syntax' 카테고리의 다른 글
C++ 형 변환 (Type Casting) (0) | 2021.03.09 |
---|---|
C++ Boolean (0) | 2021.03.09 |
C++ 자료형 (Data Type) (0) | 2021.03.09 |
C++ 전처리기 (Preprocessor) (0) | 2021.03.09 |
C++ Namespace (0) | 2021.03.09 |