jju71 님의 블로그
[Python] 컴퓨터에서 음수 표현, 2의 보수 본문
[컴퓨터에서 음수를 표현하는 방법]
부호비트란 무엇인가?
부호를 표현하기 위한 비트, 보통 최상위 비트를 말합니다. 양과 음의 값을 가진 신호인 경우에 양•음을 표시하기 위해 사용되는 비트입니다. 2진법 표시인 경우는 1단어의 선두고 부호비트가 되는 것입니다.
최상위 비트
비트 단위의 연산에서, 그 숫자값이 가장 크게 영향을 미치는 유효 숫자입니다. 즉, 그 숫자의 비트 중에서 맨 왼쪽의 비트를 말합니다.
유효숫자
측정이나 연산에 관계하여 그 측정 결과나 연산 결과의 정밀도를 주기 위한 숫자이며, 신뢰할 수 있는 숫자를 말합니다.
1의 보수(One's Complement)란 무엇인가?
어떤 수를 커다란 2의 거듭제곱수-1에서 빼서 얻은 이진수입니다. 또는 비트를 반전시켜 얻을 수 있습니다. 1의 보수는 대부분의 산술연산에서 원래 숫자의 음수처럼 취급됩니다.
80 ➜ 128 64 32 16 8 4 2 1
0 1 0 1 0 0 0 0
↓
1 1 1 1 1 1 1 1
- 0 1 0 1 0 0 0 0
= 1 0 1 0 1 1 1 1
0 1 0 1 0 0 0 0 의 모든 자리수를 반전시킨다.
1 0 1 0 1 1 1 1
➜ 이 산술연산에서 최상위 비트가 1이므로 음수처럼 취급합니다.
2의 보수(Two's Complement)란 무엇인가?
어떤 수를 커다란 2의 제곱수에서 빼서 얻은 이진수이다. 2의 보수는 대부분의 산술연산에서 원래 숫자의 음수처럼 취급됩니다. 주어진 이진수보다 한 자리 높고 가장 높은 자리가 1이며 나머지가 0인 수에서 주어진 수를 빼서 얻은 수가 2의 보수입니다. 혹은 주어진 이진수의 모든 자리의 숫자를 반전(0을 1로, 1을 0으로)시킨 뒤 여기에 1을 더하면 2의 보수를 얻을 수 있습니다.
80 ➜ 128 64 32 16 8 4 2 1
0 1 0 1 0 0 0 0
↓ 이진수 반전
1 0 1 0 1 1 1 1
+ 0 0 0 0 0 0 0 1
= 1 0 1 1 0 0 0 0
왜 현대 컴퓨터는 대부분 2의 보수를 사용하는가?
A. 간단해진 연산
1의 보수는 8비트 기준(11111111)에서 해당 숫자의 이진수를 빼는 것과 값이 같습니다.
- 반면 2의 보수는 주어진 이진수의 모든 자리를 반전시킨 후 1을 더하는 덧셈을 활용하기 때문에 컴퓨터의 하드웨어가 단순해집니다.
- 2의 보수는 덧셈결과에서 최상위 비트의 캐리(올림)을 버리면 되기 때문에, 1의 보수처럼 캐리처리나 추가연산이 불필요합니다.
1 1 1 1 1 1 1 1
+ 0 0 0 0 0 0 0 1
= 1 0 0 0 0 0 0 0 0
이처럼 8비트를 맞추기 위해 최상의 비트를 버리기만 하면 됩니다.
B. 1의 보수에서의 0문제 해결
1의 보수는 비트를 반전시켜 얻습니다.
- 0 0 0 0 0 0 0 0 을 반전시키면 1 1 1 1 1 1 1 1의 값을 얻을 수 있습니다. 하지만 이 값은 1의 보수의 체계에서는 두개의 0의 값을 얻게 됩니다.
0 0 0 0 0 0 0 0 : +0
1 1 1 1 1 1 1 1 : - 0
이런 내부 표현이 다른 같은 값을 처리하려면 CPU는 비트는 다르니까 특별처리를 해야할 일이 생깁니다.
- 그렇다면 2의 보수는 이 문제를 어떻게 해결할까?
반전시킨 1 1 1 1 1 1 1 1 에 +1을 하면
= 1 0 0 0 0 0 0 0 0
8비트를 맞추기 위해 최상위 비트를 캐리하면 0 0 0 0 0 0 0 0의 값을 얻을 수 있습니다.
‼️ 왜 최상위 비트가 1이면 음수로 취급되는가?
1 1 1 1 1 0 1 1
- 부호없는 정수(unsigned)로 보면 : 251
- 2의 보수 signed 정수로 보면 : - 5
8비트에서 signed 범위는 -128 ~ 127입니다.
- 2의 보수에서 가장 큰 값 : 0 1 1 1 1 1 1 1 = 127
- 2의 보수에서 가장 작은 값 : 1 0 0 0 0 0 0 0 = -128
10000000 ~ 11111111 → 음수
즉, signed 2의 보수로 해석할 경우에는 최상위 비트가 1이면 음수취급을 합니다.
[1.1 + 0.1 == 1.2가 False로 나오는 이유?]
부동소수점(Floating point)이란 무엇인가?
실수를 컴퓨터상에서 근사하게 표현할 때 소수점의 위치를 고정하지 않고 그 위치를 나타내는 수를 따로 적는 것입니다. 유효숫자를 나타내는 가수와 소수점의 위치를 풀이하는 지수로 나누어 표현합니다. 컴퓨터에서는 고정 소수점 방식보다 넓은 범위의 수를 나타낼 수 있어서 계산에 많이 이용되지만, 근삿값으로 표현됩니다. 또한 고정 소수점과 달리 정수 부분과 소수 부분의 자릿수가 일정하지 않으나, 유효숫자의 자릿수는 정해져 있습니다.
- 부호(sign) : 숫자의 부호(양수•음수)
- 지수(exponent) : 소수점의 위치 결정
- 가수(matissa) : 숫자의 정밀도를 나타내며, 실제 숫자 값을 저장
컴퓨터는 왜 10진수를 2진수로 변환해서 저장하는가?
- 컴퓨터의 내부 연산은 2진(0,1) 기반이므로, 10진수 입력을 2진수로 바꿔야 계산•저장할 수 있습니다.
- 2진수는 8진수•16진수로 3자리/4자리씩 끊어 변환하기 쉬어, 긴 2진수 대신 짧게 표현해 가독성과 공간을 절약합니다.
왜 일부 10진수는 2진수로 정확하게 표현되지 않는가?

- 정수/부동소수점(실수) 구분을 안한 경우
- 0.3 을 2진수로 표현해보면
⇒ 0.01001100110011.....로 '0011'의 무한반복입니다. - 정수 변환 방법을 실수에도 그대로 적용
- 자료형 범위(오버플로우) 초과
- 부호/엔디언같은 표현 차이 무시
IEEE 754 표준이란?

263.3
↓
263 = 100000111
0.3 = 0.01001100110011.....
‼️ 고정 소수점으로 나타냄 263.3 을 2진수 부동소수점 방식으로 변환방법
100000111.0100110011...으로 표현된 2진수를 맨앞에 1 바로 뒤의 소수점으로 옮겨서 표현합니다.
그렇게 하면 1.00000111010011001100....이 됩니다.
이 과정에서 소수점을 왼쪽으로 8칸 움직였기 때문에 2^8(2의 8승)으로 표현됩니다.
- 2^8의 8을 지수라고 하고 지수비트에 기록합니다.
- 소수점 이후 숫자열 전체는 가수라고 하고 연두색 부분에 기록합니다.
263.3
- 부호 비트(1bit) : 0(양수)
- 지수 비트(8bit) : 1000111 (127 + 8)
- 단정밀도(float, 지수 8bit) 는 실제 지수(actual exponent)에 127을 더한 값을 저장- 지수가 8이였지 때문에 135의 2진수를 표현
- 가수 비트(32bit) : 00000111010011001100110
금융/게임/AI 분야에서 소수 오차를 어떻게 처리하는가?
부동소수점 10진수 값에는 정확히 일치하는 이진 표현이 없습니다. 이는 CPU가 부동소수점 데이터를 표현하는 방식의 부작용입니다. 이로 인해 일부 정밀도가 손실될 수 있으며, 일부 부동소수점 연산은 예기치 못한 결과를 초래하기도 합니다.
A. dicimal 모듈 사용하기
: 파이썬의 decimal 모듈은 부동소수점의 근사값 대신, 숫자를 정확하게 표현할 수 있는 방법을 제공합니다. 특히, 금융 계산과 같이 높은 정확성이 요구되는 작업에 유용합니다.
- Decimal 객체를 사용하면 소수를 정확하게 표현할 수 있어, 부동소수점 오차를 피할 수 있습니다.
- Decimal 연산은 부동소수점 연산보다 속도가 느리기 때문에, 모든 상황에서 사용하는 것은 효율적이지 않을 수 있습니다.
from decimal import Decimal
result = Decimal('0.1') + Decimal('0.2')
print(result) # 0.3
B. 반올림 사용하기
result = round(0.1 + 0.2)
print(result)
C. 오차 허용 범위 설정하기
: 두 부동소수점 숫자가 같다는 것을 확인할 때는 직접 비교하는 대신 두 숫자의 차이가 일정 범위 내에 있는지 확인하는 것이 좋습니다.
- 복잡한 연산에 유용, 작은 오차 무시 가능
def is_close(a, b, tol=le-9):
return abs(a-b) < tol
print(is_close(0.1 + 0.2, 0.3))'Python' 카테고리의 다른 글
| [Python] 객체지향 프로그래밍(OOP) (0) | 2026.05.28 |
|---|---|
| [Python] 사용자 정의 함수 (1) | 2026.05.28 |
| [Python] 제어문_반복문 (1) | 2026.05.28 |
| [Python] 제어문_조건문 (0) | 2026.05.28 |
| [Python] 컬렉션 타입(세트, 딕셔너리) (0) | 2026.05.28 |
