컴퓨터에서 음수의 표현
음수의 표현
배경
컴퓨터에서 부호가 없는 정수를 표현할 때는 단순히 정수의 절댓값을 2진법으로 변환해서 저장해 사용할 수 있다. 하지만 음수를 표현할때에는 고려해야 할 부분이 더 생기게된다. 컴퓨터에서 음수를 표현하기위해 고안된 방법과 예시를 살펴보자
부호 절댓값법, 1의 보수법, 2의 보수법
음수를 2진수로 나타내는 법은 크게 세가지 방법이 있다. 4비트로 음수를 나타내는 세가지 방법의 예시를 살펴보자.
10진법 | 부호 절댓값법 | 1의 보수법 | 2의 보수법 |
---|---|---|---|
-8 | 없음 | 없음 | 1000 |
-7 | 1111 | 1000 | 1001 |
-6 | 1110 | 1001 | 1010 |
-5 | 1101 | 1010 | 1011 |
-4 | 1100 | 1011 | 1100 |
-3 | 1011 | 1100 | 1101 |
-2 | 1010 | 1101 | 1110 |
-1 | 1001 | 1110 | 1111 |
-0 | 1000 | 1111 | 없음 |
0 | 0000 | 0000 | 0000 |
1 | 0001 | 0001 | 0001 |
2 | 0010 | 0010 | 0010 |
3 | 0011 | 0011 | 0011 |
4 | 0100 | 0100 | 0100 |
5 | 0101 | 0101 | 0101 |
6 | 0110 | 0110 | 0110 |
7 | 0111 | 0111 | 0111 |
부호 절댓값법
부호 절댓값법은 말 그대로 부호를 나타내는 부호비트와, 절댓값을 나타내는 부분으로 나누어 값을 저장하는 방법이다. 최상위비트(MSB)가 1이라면 음수를, 0이라면 양수를 나타내면 최상위 비트를 제외한 부분은 모두 절댓값을 나타낸다.
0b 1111 // 1(-) 111(7) => -7
사람이 이해하고 다루기 쉽다는 장점이 있으나 -0과 0이 따로 있어 데이터가 하나 낭비되고, 컴퓨터의 입장에서 연산을 할때 부호에 따라 경우를 나누어야 하므로 컴퓨터입장에서는 난해한 방법이라는 단점들이 있다.
1의 보수법
보수
보수란 보충해주는 수로 N진법 수 M에 대한 보수는 M과 어떤수를 더해 N의 제곱수가 되게 보충해주는 어떤수를 지칭하는 말이다.
예를 들어 10진법 수 12에 대한 10의 보수는 더해서 100을 만드는 어떤수를 말하고, 100 - 12을 통해 12의 10의 보수는 88이 됩니다. 또한 n진법에는 n의 보수와 n-1의 보수 두가지가 존재하는데, n-1의 보수는 (n의 보수의 값 - 1)의 값을 지칭하는 말이다. 따라서 12의 9의 보수는 87이고 (100 - 12) - 1이나 (100 - 1) - 12 연산을 통해 구할 수 있고, (9의 보수 + 1) 연산을 통해 10의 보수 또한 구할 수 있다.
2진법에서의 1의 보수
2진법에서 1의 보수는 특별한 의미를 갖는다. 4비트수 1100의 1의 보수를 구하는 예를 살펴보자.
(10000 - 1100) - 1 // 2의 보수 -1
(10000 - 1) - 1100
1111 - 1100
=> 0011
1100의 1의 보수 => 0011
1100의 비트 반전 => 0011
2진법의 특성상 0과 1만이 존재하므로 2진법에서의 1의보수는 해당 비트의 반전이라는 의미를 갖게 된다.
즉 2진수에서 1의 보수는 비트 반전연산을 통해 구할 수 있고, 2의보수는 (1의 보수 + 1)를 통해 구할 수 있다.
1의 보수법
1의 보수법은 해당 양수의 모든 비트를 반전하여 음수를 표현하는 방법이다.
0110 => 6
1001 => -6
1000 => -7
0111 => 7
0000 => 0
1111 => -0
1의 보수법 덧셈연산
23 + 31
MSB
0b 0 000 0000 0000 0000 0000 0000 0001 0111 // 22
0b 0 000 0000 0000 0000 0000 0000 0001 1111 // 31
+
_______________________________________________
0b 0 000 0000 0000 0000 0000 0000 0011 0110 // 53
-23 - 31
MSB
0b 1 111 1111 1111 1111 1111 1111 1110 1000 // -23
0b 1 111 1111 1111 1111 1111 1111 1110 0000 // -31
+
_______________________________________________
0b 1 1 111 1111 1111 1111 1111 1111 1100 1000 + 1 (캐리 발생시 +1 처리 해주어야함) // -55 + 1
=> 0b 1 111 1111 1111 1111 1111 1100 1001 // -54
부호 절대값법 보다 컴퓨터가 이해하기 더 쉽다는 장점이 있으나. 덧셈시 발생하는 캐리에 따라 처리를 고려해야한다는 문제와 0과 -0의 문제는 해결되지 않았다.
2의 보수법
2의 보수법
2의 보수는 양수의 모든 비트를 반전시켜 만든 1의보수에 1을 더해 음수를 표현하는 방법이다. 다시 말해 1의 보수에서 -0인 1111을 -0인 아닌 -1에 매칭하고, 1의 보수에서 -1인 1110을 -2에 매치하는 식으로 한칸씩 미루어 생각하면 된다.
0110 => 6
1001 + 1 -> 1010 => -6
1001 => -7
0110 + 1 -> 0111 => 7
2의 보수법 덧셈연산
-23 - 31
MSB
0b 1 111 1111 1111 1111 1111 1111 1110 1001 // -24
0b 1 111 1111 1111 1111 1111 1111 1110 0001 // -31
+
_______________________________________________
0b 1 1 111 1111 1111 1111 1111 1111 1100 1010 // -54 발생한 오버플로우 캐리를 버리기만하면 됨
기존의 +0과 -0 문제를 해결하고, 덧셈 연산을 오버플로우 고려 없이 단순화 시킬 수 있어 컴퓨터의 음수 표현으로 채택된 방법이다.
파이썬에서의 음수
파이썬에서 음수는 별도의 부호필드와 절대값을 저장하고 있다가 비트 연산이 필요할 때에 2의 보수로 변환해 사용한다.
>>> bin(-5)
'-0b101'
파이썬에서 비트를 다룰때 주의할 점은 NOT 연산자인 ~이다. 다음을 살펴보자
>>> int('0b100',2)
4
>>> ~int('0b100',2)
-5
파이썬에서 내부적으로 비트연산은 2의 보수로 변환되어 진행된다.
1의 보수법(비트 반전)에서 ~4를 연산이었다면 -4가 나왔겠지만, 1의 보수법에서 -1만큼 음수를 뒤로 미룬 2의 보수법에선 -4가 아닌 -5가 나오게 된다.
또한 0b 100
의 반전으로 0b 011
을 기대했을수 있지만 정수자료형은 4바이트(32비트)이므로 사실상 0b 100
이 아닌
0b 0000 0000 0000 0000 0000 0000 0000 0100 // 4
이므로 그 반전은 다음과 같다.
0b 1111 1111 1111 1111 1111 1111 1111 1011 // -5
즉 2의 보수법에서 비트반전 ~x 연산은 -x -1의 결과를 나타낸다.
만약 0b 011
이 필요하다면 비트마스크를 통해 가능하다.
>>> MASK = 0b 111
>>> 0b 100 ^ MASK
0b 011
Leave a comment