C++ - 자료형

이강민·2023년 8월 16일

C++

목록 보기
2/22
post-thumbnail

C++ 자료형

자료형이란?
데이터의 타입

컴퓨터의 bit

다음과 같이 0 또는 1로 표현 할 수 있는 공간을 1bit라고 한다.

즉, 1bit는 212^1가지(2bit의수2^{bit의 수 })의 경우의 수를 가진다.

1byte는 8bit

왜 1byte는 8bit일까?
영문권에서 발달한 컴퓨터는 이진수로 여러가지 문자를 표현하기 위해 아스키코드를 작성하였다.
아스키코드는 128개로 작성되었으며 이는 이진수로는 7비트가 필요하였다.
27bit=1282^{7bit}=128가지
추후에 더 많은 문자를 표현하기 위해 1bit를 추가하였으며 즉, 문자 1개는 1byte면서 8bit가 되었다. 전세계의 컴퓨터 보급은 더 많은 문자를 표현할 필요가 생겼으며 기존 관행을 살리면서 한글은 2byte과 같이 개념이 확장되었다.

1bit =
0 0 0 0 0 0 0 0

컴퓨터의 단위

1byte = 8bit = 282^8
1KB = 2102^{10}byte = 1024byte
1MB = 2102^{10}KB = 1024KB = 2102102^{10}*2^{10}byte = 2202^{20}byte
1GB = 2102^{10}MB = 1024MB = 2102102^{10}*2^{10}KB = 2102102102^{10}*2^{10}*2^{10}byte = 2302^{30}byte

자료형의 종류

  • 정수형
    • char : 1byte = 8bit
    • short : 2byte = 16bit
    • int : 4byte = 32bit
    • long : 4byte = 32bit
    • long long : 8byte = 64bit
  • 실수형
    • float : 4byte
    • double : 8byte

unsigned vs signed
바이트의 표기 방법에 관한 것으로 양수, 음수를 결정하는 바이트를 사용할 것인가에 대한
명시적 방법이다.
unsigned : 바이트를 양수로만 표기
signed : 바이트를 이용하여 양수와 음수 모두 표기

char

문자형을 표기하는 방법으로 아스키코드에 따른 문자형을 제공한다.
1byte의 메모리가 할당되며 양수만 표기 할 경우 0 ~ 255까지 표현이 가능하며
음수 양수 모두 표기 시 -127 ~ 127까지 표기가 가능하다.

	//unsigned 0 ~ 255
	unsigned char c = 255;  // 255 
	unsigned char c0 = 256; //  0 
	// -1은 모든 비트가 1이다. 
	c0 = -1; //  255 

위 예시와 같이 양수만 표기 할 시 255까지 표기가 가능하며 255가 넘어가면 0을 반환한다.
c0 = -1 이 왜 255일까?
이는 컴퓨터가 음수를 표기하는 방식에서 나타나는 특징이다.
unsigned 방식은 양수만을 리턴한다. 양수 255의 비트 표기는 11111111 이다.
음수 -1의 비트 표기는 11111111로써 양수 255와 동일한데 unsigned는 양수로 표기하므로 255를 반환하는 것이다.

컴퓨터의 음수

컴퓨터의 음수는 쉽게 표현하여 -10이라면 10 + (-10) = 0이 되게 하는 비트를 의미한다.
10의 2진수 값은 8비트로 00001010이다. 모든 비트가 0이 되게 하는 2진수 값을 찾으려면 해당 진수의 보수에서 1을 더하면 된다.
즉 00001010의 보수는 11110101이 되고 1을 더하면 11110110이 된다.
다시 00001010 + 11110110 = 100000000 8비트가 넘어가는 수는 생략하여 00000000이 된다.

signed에서는 앞서 말한 듯이 음수를 표현한다고 하였다.
따라서 8비트 중 모든 비트가 1이되는 수 255를 넣으면 -1이 되는 것이다.

// 1바이트로 양수, 음수 둘다 표현 
//signed -127 ~ 127 
char c1 = 255;  // -1
char c2 = -1; // -1

실수형 float와 double

실수형 float는 4바이트, double은 8바이트가 할당된다.
실수형은 어떻게 비트로 변환이 될까?

부동소수점

다음 결과를 예측해보아라

int main () {
	float num1 = 0.1;
	float num2 = 0.2;
    float num3 = 0.3; 
    
	printf("%d", num1 + num2 == num3);
    
    return 0;
}

결과부터 말하자면 printf는 0을 표기한다. 0.1 + 0.2가 0.3이 아니라는 말이다.

왜 이런 결과가 나왔는지 컴퓨터가 실수를 어떻게 표현하는지 이해가 되면 쉽게 풀이가 된다.

컴퓨터가 실수를 저장하는 방식은 개략적인 값으로 저장한다.

실수는 2진수로 표현이 될때 다음과 같이 변환된다.

소수점 아래는 다음과 같은 규칙이 적용된다.
0.12진수0.1_{2진수} 은 다음과 같이 표현된다. 0.510진수0.5_{10진수} 즉, 0.1은 0.1을 더하면 자리 수가 바뀌 듯 0.5는 + 0.5가 되면 자리수가 바뀐다.
이러한 수학적 패턴으로 2진수의 소수를 10진수로 표현하면 다음과 같다.

2진수 10진수
0.1 0.5 (2-1)
0.01 0.25 (2-2)
0.001 0.125 (2-3)
0.0001 0.0625 (2-4)
0.00001 0.03125 (2-5)

0.1 + 0.2 과 0.3은 같지 않다.

위 규칙을 적용하면
0.3의 2진수 값은 무한소수로 0.0100110011...0.0100110011...
즉 2진수로 0.3과 가장 근접한 값을 내놓는다.
0.2의 2진수는 0.00110011...0.00110011... 마찬가지로 무한소수로 0.2와 가장 근접한 값을 내놓는다.

0.1 + 0.2에서 0.2는 2진수로 변환된때는 0.2의 가수는 0.00110011...고 양수 0에 진수 부분은 8비트로 00000000이된다. 0.2의 이진수는 00000000000110011... 인데 가수부분은 float는 32비트로 부호부분과 진수부분 9비트를 제외한 23비트를 표현하여 이하 무한소수는 절삭한다. double은 64비트이므로 부호 1비트에 진수부분 8비트를 제외한 55비트만큼 표현하여 절삭한다.
마찬가지로 0.1은 부호와 진수를 포함하면 0000000001000000...
0.1 + 0.2는 2진수로
0000000001000000...+00000000000110011...=000000000101100110011...0000000001000000... +00000000000110011... = 000000000101100110011... 이 된다.
0.3은 0000000000100110011...가 되므로 000000000101100110011...와 같지 않으므로 0(false)가 된다.

위를 근거로 float 타입의 0.2와 double 타입의 0.2는 서로 다를 수 있다.

double d = 0.2;
float d2 = 0.2;

printf("%d", d == d2); //0
// 서로 다른 결과이다. 

연산 할때는 같은 타입으로

double형과 float의 연산 결과가 다르 듯이 마찬가지로 실수형을 포함하고 있는 연산이 있다면 되도록이면 같은 타입끼리 연산을 하고 만약 어쩔 수 없이 다른 타입이 연산에 포함된다면
명시적으로 의도하는 타입으로 형변환 뒤 연산을 진행하자

	float f = 10.2421f + (float)20;
	printf("%f", f);

정리

  • 1바이트가 8비트인 이유
    • 영미권에서 사용하던 관습
  • unsigned와 signed의 차이
    • 양수만 포함하던가 음수와 양수를 포함하던가의 차이
  • 컴퓨터가 음수를 비트로 바꾸는 법
    • 10의 음수는 더하기 연산을 통해 0이 되는 수이다.
  • 실수형에 대한 연산과 특징
    • 소수점은 개략적으로 저장된다. 가수부분이 타입의 크기에 따라 절삭되어 서로 다른 결과를 만들어 낸다.
  • 되도록 같은 타입끼리 연산
    • 불가항력적인 경우에는 명시적 형변환을 통해 연산을 하자.
    • 실수형은 정수로 변환하여 계산하는 것이 정밀하다.
profile
AllTimeDevelop

0개의 댓글