[DataStructure] - 데이터의 비트 표현


데이터는 컴퓨터에서 비트(Bit)으로 표현된다. 비트는 최소 단위인 2진수 값을 하나 저장할 수 있는 메모리 크기이다.

바이트는 8개의 비트의 집합이다.

2. 정수


이미지

양의 정수는 보통 4바이트(32비트)로 표현한다.

4바이트로 표현 할 수 있는 최대 정수는 2,147,483,647이다.

32비트의 가장 첫 비트양수는 0, 음수는 1로 저장하는 부호 비트이다.

이를 MSB (Most Significant Bit - 최상위 비트) 이라고 부른다.

음의 정수2의 보수법으로 표현한다.

예를 들어 -217을 표현하고 싶다면 먼저 217을 2진수로 표현하고 0은 1로, 1은 0으로 바꾼 뒤, 1을 더한다.

여기서 2의 보수법으로 표현하지 않으면 양의 비트와 음의 비트를 더했을 때 0이 되지 않는다.

2의 보수법을 통해 더했을때 overflow시켜 0으로 만들어버린다.

2. 실수


실수를 표현하는 가장 쉬운 방법은 실수부소수부를 나눠서 비트로 표현하는 것이다.

이를 고정 소수점 방식이라고 한다.

하지만 이렇게 할 경우 정수부를 늘려 큰 숫자를 표현할 수 있지만 소수부가 줄어서 정밀해지기 어렵고 소수부를 늘려서 정밀하게 가면 정수부가 줄어서 큰 숫자를 표현할 수 없다.

그래서 소수점을 둥둥 떠 다닐 수 있게 하는 부동 소수점 방식이 나왔다.

부동 소수점 방식은 지수를 통해서 표현하는 방식이다.

예를들어 263.3이라는 소수를 2진수로 표현해보면

100000111.010011001100110… 으로 표현되는데 실수부를 1만 남기고 전부 뒤로 빼면

1.00000111010011001100110… * 2^8 로 표현이 된다.

  • 2^8에서 8을 지수라고 하고 지수부에 기록한다 (8비트)
  • 나머지 소수부를 1을 제외한 0.00000111010011001100110…을 실수부에 기록한다. (23비트)

이미지

그렇게 되면 아래와 같이 표현된다.

  • 부호 비트 (1 bit) : 0 (양수)
  • 지수 비트 (8 bit) : 10000111 (127 + 8 = 135)
  • 가수 비트 (23 bit) : 00000111010011001100110

바이어스 상수 : 2 ^ (n-1) -1 n : 지수 비트 수

지수 비트에 있는 값에 바이어스 상수 (127) 을 더하는 이유는 8bit에서도 음수와 양수를 표현해야하는데 그러면 거기서 1비트를 또 부호비트로 써야한다. 그래서 8bit으로 표현할 수 있는 숫자의 범위를 음과 양으로 쪼개서 0000 0000 ( -127 ) ~ 1111 1111 ( 128 ) 일반적으로 정수와 지수의 차이가 있기 때문에 밑이 양수면 아무리 음수여도 양수가 된다. 그리고 무한대로 0에 가까워지지 0보다 큰 숫자이다.

여기서 주의점은 0.3을 정확히 나타낼 수 없다는 것이다.

0.010011001100110을 10진수로 바꾸면 0.29998779296875이다.

그렇기 때문에 언어마다 0.1을 100번 더 하면 10이 나오지 않고 9.9999999998등이 나오는 오류가 발생한다.

2-1. 부동 소수점 오류


부동 소수점 방식에는 오류가 발생한다.

>>> 0.2 * 3 == 0.6
False
>>> 1.2 - 0.2 == 1.0
True
>>> 1.2 - 0.1 == 1.1
False
>>> 0.1 * 0.1 == 0.01
False

위와 같이 단순 비교는 부동소수점에서 정확하지가 않다.

이걸 해결하는 방법은 round 함수로 반올림을 하는 방법과 decimal 라이브러리를 사용하는 방법이 있다.

decimal에 문자로 소수를 넣어주고 연산을 하면 정상적으로 동작한다.

>>> import decimal
>>> decimal.Decimal('0.1') * 3 == decimal.Decimal('0.3')
True
>>> decimal.Decimal('0.3') + 2
Decimal('2.3')

하지만 아래와 같이 사용하면 똑같이 오류가 생기는 것을 볼 수 있다.

>>> import decimal
>>> decimal.Decimal(0.1 *3)
Decimal('0.3000000000000000444089209850062616169452667236328125')

3. 문자열


Python은 C언어와 다르게 char라는 character 타입이 존재하지 않고 전부 String 타입이다.

1개의 문자도 길이가 1인 문자열로 인식한다.

문자열은 List구조처럼 인덱싱을 할 수 있다.

>>> a = "qwe"
>>> a[0]
'q'
>>> a[1]
'w'
>>> a[2]
'e'