컴퓨터 과학 기초발행일 2024. 5. 15.원본 https://blog.naver.com/jword_/223445705923 ↗

unsigned signed의 개념

unsigned signed의 개념 — #unsigned #signed #bitinteger #개발자의 도구들 컴퓨터공학과 학사과정 중 공부한 내용을 정리하였습니다...

#Basic keyword#Naver Blog

#unsigned #signed #bitinteger #개발자의 도구들

​

컴퓨터공학과 학사과정 중 공부한 내용을 정리하였습니다.

\* 본글은 PC버전에 최적화 되어있습니다.

​

​

이미지

컴퓨터에서의 정보 표현

view

컴퓨터는 정보를 어떻게 표현할까요? 우리가 화면에서 보고 있는 글자는 컴퓨터는 어떻게 인식할까요?

​

컴퓨터는 정보를 이진수인 0과 1로 모든 정보를 표현을 합니다. 이진수를 사용하는 이유는 다양하겠지만, 전기신호를 이용하기 때문이라고 할 수 있겠습니다.

​

컴퓨터는 전기신호를 받아야만 동작하는 기계인데요. 이 전기신호는 특성상 이진수로 표현하는 것이 가장 효율적이라고 볼 수 있겠습니다. 전기신호로 정보를 해독하는 방법은 정말 단순합니다. 신호가 약하면 0, 신호가 강하면 1입니다. 하지만, 강하고 약하다는 개념은 상대적이기 때문에, 보통은 일정 역치를 기준으로 신호를 0과 1로 나누고 있습니다.

​

역치를 3등분으로 나눌 수도 있겠습니다만, 그렇게 한다면 기준이 매우 모호해지며, 정보에 오류가 많이 발생할 가능성도 높아집니다. 따라서 가장 단순한 0과 1신호로만 해석하도록 정하였고, 이 룰에따라 오늘날의 모든 컴퓨터는 만들어지게 되었습니다.

​

전기신호는 빠르지만 불안정한 특징이 있는데, 매개체에 따라 본래 신호보다 약해질수도, 강해질수도 있습니다. 이런 불안정한 특징때문에, 원래의 정보와는 다르게 해독할 가능성도 있습니다. 하지만, 발전을 거듭하면서, 오늘날의 컴퓨터는 정보 오류에 충분히 대응 할 수 있는 상태가 되었습니다.

​

전기신호를 사용하기 때문에, 속도가 매우 빠릅니다(광속). 그래서 정보를 받아들이는 속도도 빠르고, 연산속도도 그만큼 빠른 것이지요.


bit를 이용한 수 표현

먼저 이진 수에 대한 이야기를 해봅시다. 수학시간에는 보통 "이진수"를 "십진수"로 변환하여 계산하는 문제를 풀어본 경험이 있을 것입니다. 우리가 십진수 체계에 익숙해져있어서 그런지, 이진수를 봤다하면, 십진수로 변환하는 경우가 많습니다. 이는 편하게 이진수를 편하게 사용하기 위한 자연스러운 방법입니다.

​

컴퓨터 역시 이 이진수 체계를 사용하여 숫자를 표현합니다. 하지만, 우리가 일반적으로 알고 있는 방식과는 다릅니다. 컴퓨터는 숫자로 표현할 비트수를 정해놓고 사용합니다. 즉, 한계를 정해놓고 수를 사용한다고 보시면 될 것 같습니다.

​

우리가 보기에 1111은 숫자 15인데, 컴퓨터는 이를 다르게 해석할 수 있습니다.

​

Integer

바이트는 8개의 비트 묶음입니다. 1바이트로 표현가능한 정보는 2⁸으로 총 256가지의 정보 표현이 가능하며, 숫자 0부터 255까지의 수 표현이 가능합니다.

​

앞서 컴퓨터는 한계를 정해놓고 숫자를 표현한다고 하였습니다. Integer가 그 대표적인 예시입니다. integer은 보통 4바이트(32비트)로 정해두는데 표현가능한 경우의 수는 2³²가지입니다. 이는 4,294,967,296가지의 경우의수를 가집니다. 즉 0과 양의 정수로만 따졌을때 4,294,967,295까지의 수표현이 가능한 것입니다.

​

하지만, integer은 정수로, 정수는 양수 뿐아니라 음의정수도 존재합니다. 4바이트의 제한된 공간을 가지고 양과 음의 정수 그리고 0까지 공평하게 표현하기 위해 Integer는 비트를 나누게 되었습니다. 그래서 최대 음의 정수로는 -2,147,483,648까지, 양의 정수로는 2,147,483,647까지 표현이 가능하도록 제한해 두었습니다.

​

이 범위를 벗어난 값을 integer로 표현하려고 하면 overflow 오류가 발생합니다.

​

여기서 의문이드는 부분이 있습니다. "어떻게 음수를 표현하지? -1001 이런 비트는 본적이 없는데...?". 맞습니다. 저희는 확실히 이진수를 배우면서 -1001 같은건 보지 못했습니다. 이진수에서 음수를 표현하기 위해 특수한 방법을 차용하였습니다. 바로 최상위 비트를 양수, 음수에 대한 정보로 사용하기로 한 것입니다.

​

최상위 비트가 0인 경우 양수(와 0), 1인 경우 음수로 표현하도록 하였습니다. 최상위 비트가 수 표현에서 제외된 덕에, 최대 0부터 4,294,967,295까지 표현 가능한 수가 반으로 줄어 -2,147,483,648 ~ 2,147,483,647까지만 표현 가능하도록 바뀌었습니다.

​

unsigned vs signed

³⁴⁵⁶⁷⁸⁹

이를 이해하기 위해, unsigned와 signed에 대한 개념이 필요합니다. 앞서 Integer은 약 -21억부터 21억까지 표현이 가능하다고 하였습니다. 이는 부호있는 정수 표현인데, 이를 signed라고 부릅니다.

​

하지만, 여러분이 Integer을 사용한다고 가정해봅시다. 여러분은 오직 연산(로직)에 음수를 절대 사용하지 않을 수 있습니다. 하지만, Integer를 그냥 선언하면, 음수를 사용도 안하는데, -21억만큼이나 사용을 할 수 없게됩니다.

​

사용하지도 않을 음수때문에 정보 표현에 제약이 걸리는 것은 매우 불편한일입니다. 이를 해결하기 위해서는 Integer를 unsigned로 선언하여 음의 정수 표현을 포기할 수 있습니다. 0과 양의 정수만으로 32비트를 꽉 채워 사용할 수 있게됩니다. (0~4,294,967,295) 이게 unsinged의 개념입니다. 음의 정수를 표현하지 않고 0과 양의 정수만 표현가능하도록 만든 것입니다.

​

unsigned와 signed는 프로그래머의 재량에 달려있습니다. unsigned의 경우 표현할 수 있는 범위가 늘어나지만, 음의 정수를 사용할 수 없어 프로그램 내에서 음수없이 코드를 짜야합니다. 반면 signed는 음의 정수를 표현할 수 있지만, 수표현의 범위가 좁아져, 범위보다 큰 수가 안나오는 프로그램을 짜야하겠습니다.

​

|절댓값|

signed의 최솟값과 최댓값에는 특징이 존쟇바니다. 바로, |MIN| = |MAX| + 1이라는 것 입니다. 또한 singed를 unsgined로 변경시 최댓값은 |U\_MAX| = 2 \* |S\_MAX| + 1입니다.

​

비트의 음수 표현

³⁴⁵⁶⁷⁸⁹

비트의 음수값을 십진수로 쉽게 계산하는 방법을 알아보겠습니다. 비트에는 보수라는 개념이 있는데, 이를 직감적으로 이해하기가 매우어렵습니다. 그냥 공식처럼 외우는 걸 추천드립니다.

​

2의 보수

예를 들어 0101(5)을 2의 보수로 표현하려면 1. 0과 1을 모두 뒤집고, 2.뒤집은 수에 +1을 계산합니다. 1011로(-5)가 되는 것입니다.

그럼 1011의 2의 보수는 얼마일까요? 1011은 11로 2의 보수로 변환하면, 0101이되는데요. 이게 -11일까요?

앞서 signed의 개념을 설명하면서 언급한게 있습니다. 바로 음수를 표현할때는 최상위 비트 한 개를 희생한다고 하였습니다. 즉 1011은 애초에 4비트 수로, signed로 표현할때 양수표현에 한계가 있습니다. 0000 ~ 0111 (0~7) 즉 11이라는 수는 4비트 signed로는 표현할 수 없는 수 입니다. 따라서 4비트로 표현할때는 -8에서 +7까지만 표현이 되는 것이지요.

​

앞서 1011을 너무 자연스럽게 -5라고 언급하였는데, 이는 아주간단한 계산로직 적용하여 구할 수 있습니다. signed 수에서 최상위 비트가 1인 경우 해당 최상위 비트의 값에 -를 붙여서 계산하면 됩니다. 즉 1011 = 1 + 2 + -(8) = -5입니다. 이는 정확히 양수 5를 2의 보수 취한값과 일치합니다.

​

signed to unsigned

³⁴⁵⁶⁷⁸⁹

프로그램을 작성하다보면, unsigned를 signed로 signed를 unsigned로 변환해야할 때가 있습니다. 특히나, 둘을 함께 비교하거나, 연산할때 주로 변환이 일어납니다.

​

singed가 0혹은 양수 값일 경우에는 unsigned로 변환하는데 큰 문제가 없지만, 음수에서 양수로 변환할때는 특정한 규칙이 있습니다. 아래 표를 보시고 직접 규칙을 찾아보세요.

이미지

어떤 규칙이 있는지 조금 보이시나요? 네 바로 음수에 2ⁿ(비트 수) 만큼 더해주면 바로 양수로 변환이 가능합니다.

이미지

Explict / Implicit casting

이는 보통 언어에서 자동으로 구현되어있는 경우가 많습니다. 즉, 우리가 unsigned와 singed를 맞춰주지 않아도 알아서 형식을 맞춰 계산을 해주는 것이지요. 이를 Implicit casting이라고도 부릅니다. 아래 예제를 보면서 다시 정리해보겠습니다.

​

int tx, ty; unsigned ux, uy;tx = ux;uy = ty; ​\* u = unsigned t = signed

위의 예제에서 tx = ux;는 unsinged로 선언된 변수가 암묵적(Implicit\_into, in)으로 tx로 캐스팅 됩니다. 앞서 설명한대로 ux의 값이 tx가 표현가능한 양수를 벗어난다면, 데이터 손실이 발생할 수 잇습니다.

uy = ty; 역시 signed로 선언된 정수를 unsigned로 암묵적으로 변환합니다. 이 역시 ty가 음수 데이터 일경우 uy로 변하면서 데이터 손실이 일어날 수 있습니다.

​

Explicit Casting

명시적(Explicit\_open) casting은 이와 반대로 직접 명시적으로 캐스팅(throw)할 자료형을 입력해줍니다.

int tx, ty; unsigned ux, uy;tx = (int) ux;uy = (unsinged) ty; ​\* u = unsigned t = signed

Evaluation : Implict Casting

앞서 unsigned와 signed가 비교연산에 함께 사용될 수 있다고 하였습니다. 보통 C언어에서는 Implicit Casting을 해주기 떄문에, 모든 변수에 대해 casting을 입력해 줄 필요가 없는데요. unsinged와 signed가 함께 비교된다면, 어디에 맞춰 비교를 하게 될까요?

​

이미지

\*Unsigned는 suffix에 보통 U를 붙인다./ 32비트, 즉 4바이트 Integer 형이다.

위 예시를 보고 어디로 맞춰 평가가 되는지 스스로 유추해보세요. singed는 unsigned와 비교시에무조건 unsinged로 Implicit casting이 되어 무조건 비교가 들어갑니다. 하지만, singed끼리의 비교는 형변환이 일어나지 않습니다. 위 식의 비교결과를 아래에 출력해보겠습니다.

int 0 == unsinged int 0U // trueint -1 < int 0// trueint -1 < unsinged int 0U ​// falseint 2147483647 > int -2147483647 - 1 // trueunsinged int 2147483647U > int -2147483647 - 1 // falseint -1 > int -2 // true(unsigned)int -1 > int -2 // trueint 2147483647 < unsinged int 2147483648U // trueint 2147483647 > (int) 2147483648 // True

여기서 주목할만한 부분을 빨간색으로 표시두었습니다.

​

  1. int -1 < unsigned int 0U

int -1을 unsinged로 casting하면 unsigned의 최댓값이 됩니다. 1111 1111 1111 1111 ...

​

  1. unsinged int 2147483647U > int -2147483647 - 1

int형을 unsigned로 변환시 2147483648U 이 됩니다.

​

  1. (unsigned) int -1 > int -2

int -1은 1111 1111 1111 ... 으로 unsigned의 최댓값을 나타낸다.

singed의 음수 표현은 이진수로 1000 1001 0110 등의 형태로 나타나는데 이를 그대로 양수로 계산하면 된다.

​

  1. int 2147483647 > (int) 2147483648U

2147483648U는 signed에서 양수 범위를 초과함. 비트로 나타내면 1000 0000 0000 ..000 인데 이는 음수로 -2147483648에 해당하는 값이다.

​

​