C 실수 자료형의 오차
변수에 저장되는 값은 0,1의 비트 꼴이라는 것은 알고 있다.
int 자료형의 경우, 맨 앞의 sign bit는 +, -를 나타내고, 그 뒤의 비트들은 이진법으로 정수 값을 나타낸다.
float, double 등 실수 자료형을 비트로 저장하는 방법에는 1. 고정소수점 방식 2. 부동소수점 방식이있다.
1. 고정소수점 방식
실수를 정수 부분, 소수 부분으로 나누고 그 사이에 소수점(.)이 있다고 생각하게 표현한 것.
float의 경우 4 byte == 32 bit 이므로, 맨 앞에는 부호 bit가 오고 그 뒤에 15bit는 정수를 표현하고 나머지 16bit는 소수점 뒷 부분을 표현한다. double의 경우 8 byte니까 정수부가 31 bit, 소수부가 32 bit다.
정수부분은 소수점이 놓이는 위치 기준 바로 앞 bit가 2^0, 그 앞 bit가 2^1 등등 정수 자료형 저장하는 것과 같은 개념이다.
소수부분은 소수점이 놓이는 위치 기준 바로 뒤부터 시작해 2^-1, 그 다음 bit는 2^-2 등등 지수가 점점 감소한다.
예를 들어서 7.75를 float에 고정소수점으로 저장하면 저장된 bit는 다음과 같이 생겼을 것이다.
0 000000000000111 . 1100000000000000
소수점 앞 정수 부분은 이진법으로 7을 나타내고 있고, 소수점 뒤의 소수 부분은 2^-1 + 2^-2 값인 0.75를 나타내고 있다.
소수점 앞 뒤로 이진법으로 나타내기만 하면 되니 고정소수점은 구현하기가 편리한 장점을 가지고 있다.
하지만 높은 정밀도를 갖추지 못한다는 것이 엄청난 단점이다.
예를 들어 float의 경우 소수부가 16 bit이기 때문에 표현할 수 있는 가장 작은 소수 부분의 숫자는
2^-16 == 0.00001525878 이다. 이것보다 더 적은 숫자는 표현할 수 없는 것이다. 또한 정수 부분은 15개의 bit를 가지고 있으니 최대로 표현할 수 있는 수는
2^15 - 1 == 2^14 + 2^13 + ... 2^0 == 32767 이다.
그렇기 때문에 더 큰 수, 더 정교한 수를 표현할 때는 부동소수점 방식을 사용한다.
2. 부동소수점 방식
맨 앞에는 sign bit를 가지고 그 뒤에 지수부, 가수부를 통해서 표현한다.
float 자료형은 4byte다. 맨 앞 1 bit는 부호, 그 다음 8 bit는 지수부, 나머지 23 bit는 가수부다.
double 자료형은 8byte다. 맨 앞 1 bit는 부호, 그 다음 11 bit는 지수부, 나머지 52 bit는 가수부다.
부동소수점 방식으로 표현해보기. https://www.youtube.com/watch?v=RuKkePyo9zk
추가적으로, 12와 같은 숫자는 컴파일러가 기본적으로 정수, int 형인 것으로 인식하는 것 처럼 123.45와 같은 실수형 리터럴은 컴파일러가 기본적으로 double 타입으로 인식한다.
그렇기 때문에 float x = 123.45; 처럼 float 형 x 변수에 123.45 리터럴을 할당해 초기화 시키면, double 타입 8byte인 123.45가 float 4byte로 typecasting 되기 때문에 더 작은 자료형으로 변환되며 손실되는 비트가 있을 수 있다.
이런 손실을 방지하기 위해서는 float 변수에 실수 리터럴을 집어넣을 때는 뒤에 f를 붙여준다. float x = 123.45f
그러면 컴파일러는 f 앞의 실수를 float 타입으로 인식하고 x 변수에 할당해서 float가 float에 할당되기 때문에 손실이 발생하지 않는다.
'공부 > TIL' 카테고리의 다른 글
[TIL]2022/03/22 C 다중소스 분할 컴파일 (0) | 2022.03.22 |
---|---|
[TIL]2022/03/09 (0) | 2022.03.09 |
[TIL]2022/03/05 (0) | 2022.03.05 |
[TIL]2022/03/01 (0) | 2022.03.01 |
[TIL]2022/02/22 (0) | 2022.02.22 |