' [C/C++] 4강 - 자료형에 대하여··· (부동 소수점, ASCII, signed & unsigned)

Programming/C & C++

[C/C++] 4강 - 자료형에 대하여··· (부동 소수점, ASCII, signed & unsigned)

mdisprgm 2021. 6. 6. 21:07
728x90
728x90

이 글은 C언어에서 사용되는 자료형에 대해 자세히 얘기하는 내용이다.

 

이전의 강좌들에 넣기엔 분량이 너무 많아져 생략했던 것들을 모았다.

 

(1) 정수 타입

C언어에서 사용할 수 있는 정수 타입 종류 아래와 같다.

short 		//2Bytes
int 		//4Bytes
long	  	//4Bytes
long long 	//8Bytes

저 중에서 int를 가장 많이 쓰게 될 것이다.  

 

각 타입의 size는 개발 환경마다 상이할 수 있다는 걸 알아두자.

 

 

정수 타입의 범위를 구하는 법은

 

지난 강좌 2강(변수)에서 다뤘으므로 생략함.

 

(2) 고정 소수점과 부동 소수점 (float, double)

컴퓨터에서 실수를 표현하는 방식은 크게 두 가지로 나눌 수 있다.

 

1. 고정 소수점 (Fixed Point)

2. 부동 소수점 (Floating Point)

 

 

고정 소수점은 말그대로 소수점이 고정된 것이고,

부동 소수점도 말그대로 소수점이 움직인다는 것이다.

 

ㄱ) 고정 소수점

 

예를 들어 32Bits 중 절반16개는 정수, 나머지 절반16개는 소수점 부분의 숫자를 저장하는 것이다.

실제로 정확한 고정 소수점의 형태는 아니고 보고 이해하기 쉽게 그린 것

2.3이 고정소수점 형태로 저장된 것을 그림으로 그렸는데

 

어렵지 않으니 금방 이해할 수 있을 것이다.

 

그런데 고정 소수점엔 치명적인 단점이 하나 있는데, 바로

 

소수점이 고정되기 때문에 비트 낭비가 있을 수 있다.

 

 

예를들어서

 

위에서 그린 2.3의 소수점은 3이라서 비트 두 개만으로도 표현할 수 있는데

 

비트를 네 개나 쓰고 있으니, 낭비라고 할 수 있다.

 

또한 2보다 훨씬 큰 정수를 표현하고 싶을 때

 

그리고 소수점 부분은 비트가 많이 필요하지 않을 때

 

만약 소수 부분은 비트를 두 개만 쓰고

 

나머지를 정수 부분에 양보할 수 있다면 메모리를 더 효율적으로 사용할 수 있을 것이다.

 

이것을 해결하기 위해 나온 것이 바로 부동 소수점(floating point)이다.

 

 

ㄴ) 부동 소수점

 

C언어에서 사용하는 실수 자료형인 float과 double이 바로 IEEE754 표준에서 정의하는 부동 소수점을 따른다.

 

부동 소수점이 실수를 표현하는 방식은 생각보다 복잡하니 꼼꼼히 읽어야 한다.

 

이 포스팅만으로 이해가 안 간다면 다른 자료라도 찾아봐서 이해한다면

 

더 좋을 듯하다.

 

 

12.345으로 예를 들자면

 

먼저 이를 과학적표기법으로 표기해야 한다.

 

12.345은 과학적 표기법으로 

 

\(1.2345 \times 10^{1}\)

 

같이 표기할 수 있다.

 

이때 소수점의 위치의 따라 10의 지수도 변할 수 있는데

 

\(1.2345 \times 10^{1}\)처럼 소수점 앞에 자리가 0이 아닌 한 자릿수라면

 

그것을 정규화(normalization)라고 한다. 즉, 12.345를 정규화로 표기하면

 

\(1.2345 \times 10^{1}\)가 되는 것!

 

 

IEEE754을 따라서 부동 소수점이 저장될 때는

 

일단 수를 2진수로 변환하고 정규화식으로 표현하는데

 

8.5 에 그 과정을 적용하면 아래와 같다.

 

\(8.5 => 1000.10_2 => 1.00010 \times 2^3\)

 

 

그리고 여기서 다음 세 가지를 뽑아내는데

 

- 부호 : 0 (0이면 +, 1이면 -)

- 지수 : 130 (지수는 3이지만 IEEE754표준에서는 지수 + 127 을 저장하는데, 이 127을 bias라고 함, 이 bias를 더하는 이유는 지수가 음수일 때 연산을 쉽게 하기 위해서..)

- 가수 : 00010000000000000000000 (정규화식에서 소수점 뒷부분, 모자라는 부분은 0으로 채움) 

 

이 세 가지를 아래 그림과 같은 구조로 저장하여 사용한다.

결론적으로 8.5를 부동소수점에 저장한다면 아래와 같이 된다.

 

(부호)    (지수 \(130_2\))                (가수)

   0         10000010       00010000000000000000000

 

 

그러나 슬프게도 부동 소수점에도 역시 단점은 존재하는데..

 

그것은 바로

 

1. 정밀도

2. 성능

이다.

 

부동 소수점은 고정 소수점에 비해 성능과 정밀도, 모두 뒤쳐진다.

 

정밀도가 떨어지는 이유는 컴퓨터가 이진법으로 계산하기 때문인데

 

8.5같은 경우 오차없이 이진법으로 표현할 수 있는 수라서 예시로 든 것이고

 

그렇지 않은 수들은 소수점이 무한대로 뻗어나간다. (무한소수)

 

대표적인 게 0.1인데, 0.1을 이진 정규화식으로 표현하면 무한소수가 된다.

 

그래서 컴퓨터로 0.1 * 0.1 을 계산하면 0.01이 나오지 않는 것이다.

 

보시다시피 오차를 확인할 수 있다.

(%.Nlf 이렇게 하면 출력할 소수점 자릿수를 지정할 수 있습니다)

 

지금까지 설명한 것이 4Bytes의 크기인 float의 경우였고

 

double은 float 비트 수의 정확히 2배, 따블로 되어있어서 double이라고 한다.

 

 

일반적으로 부동 소수점의 정밀도는 float의 경우 약 5자리까지, double의 경우 약 10자리까지 오차 없이 표현할 수 있다고 한다.

 

 

(3) unsigned와 signed

int 등 수를 저장하는 자료형은 모두 부호를 의미하는 비트를 가지고 있다.

 

최상위 비트 하나가 부호를 의미하는데

 

0이면 양수, +

1이면 음수, - 가 된다.

 

ex)

1001 - 최상위 비트가 1이므로 음수

0001 - 최상위 비트가 0이므로 양수

 

 

signed int의 범위는 지난 강좌에서 말했듯

 

-2,147,483,648 ~ 2,147,483,647 이고

 

unsigned int의 범위는 0 ~ 4,294,957,295 까지이다.

 

usigned는 1001 도 음수로 인식하는 게 아니라

 

01001 을 계산하듯이 한다. (비트가 늘어나는 것은 아니다, 다만 셈(count)을 그렇게 한다는 것이다)

 

 

signed는 비트 하나를 부호를 위해 사용하기 때문에

 

표현할 수 있는 범위의 최대값의 절대값이 절반이 됐다.

 

전체 범위에서 절반을 나눠서 - 쪽으로 양보하는 것이다(수직선에서 왼쪽..).

 

(4) char형과 ASCII

char형.

 

1바이트 크기를 가진 문자를 위한 자료형이라고 알고 있을 것이다.

 

그런데 범위를 논할 땐 꼭 -128~127로 얘기를 한다.

 

이는 단순히 256가지 값을 표현할 수 있다는 것을 비유로 얘기하는 것이 아니라,

 

실제로 그 숫자들을 저장하여 문자를 표현하기 때문이다.

 

 

컴퓨터는 모든 문자를 정해진 숫자에 대응시켜서 표현(문자 인코딩)하는데

 

예를 들어

 

'A' : 65

'B' : 66

...

'Z' : 90

 

'a' : 97

'b' : 98

...

'z' : 122

 

이런 식이 된다.

 

대문자 A부터 65, 소문자 a부터 97에 대응시키는 인코딩 방식이 바로 ASCII라는 C언어에서 사용하는 표준이다.

 

이 ASCII에서는 0~127의 숫자를 알파벳과 일부 특수문자와 대응시키게 된다.

 

아래는 위키백과에서 퍼온 ASCII 전체 표이다.

클릭 시 원본 이동

 

printf로 char형을 %d로 출력한다면 ASCII값을 확인할 수 있다.

#include <stdio.h>

int main() {
	printf("%d %d\n", 'A', 'c');
}

 

또 단일 문자 자체를 컴파일러가 숫자로 인식하기도 하기 때문에

 

이런 것도 가능하다

#include <stdio.h>

int main() {
	printf("%d - %c\n", 'A' + 5, 'A' + 5);
}

A부터 5번째 뒤, 즉 6번째 알파벳인 F와 F의 ASCII인 70이 출력된다.

 

 

 

(5) 추가 서식 문자들

이전 강좌에서 설명하지 못했던 서식 문자들이다.

 

unsigned와 signed의 서식 문자를 구분하여 설명하는데

 

short 등 printf 강좌에서 설명하지 못한 것도 추가했다.

 

서식 문자 용도
%u unsigned int
%e, %E 실수를 지수표기법으로 출력함
%g, %G %f와 %e,%E 중 더 짧은 것을
알아서 선택해줌
%hhd char형을 %d로 출력할 때 나오는 그 ASCII값으로 받아들임.
scanf("%hhd",&ch); 이럴 때 65를 입력하면 ch에는 A가 저장됨.
%hd signed short
%hu unsigned short
%lu unsigned long
%llu unsigned long long

 

이것 말고도 더 많은 서식 문자들이 있지만.. 이정도만 알고 있어도 당장은 지장이 없기 때문에

 

그때 그때 필요한 걸 찾아쓰면 된다! 구글에 검색하면 1초 만에 나오는..

 

 

끝.

728x90
728x90
'