파이썬 정수의 임의 정밀도 구현을 이해하고 비트 연산과 나눗셈 함정을 마스터한다.
🎯 이 강의에서 배우는 것
파이썬에서 2 ** 1000을 실행하면 즉시 결과가 나옵니다. C 언어에서는 오버플로우가 발생하는 상황입니다. 이 강의에서는 파이썬 정수가 내부적으로 어떻게 구현되어 있는지, 비트 연산이 어떤 실용적인 용도가 있는지, 그리고 나눗셈 연산자를 잘못 사용할 때 생기는 함정을 깊이 이해합니다.
♾️ 임의 정밀도 정수 — 오버플로우가 없는 이유
C 언어의 int는 32비트(또는 64비트)로 표현할 수 있는 정수 범위가 고정되어 있습니다. 이 범위를 넘으면 오버플로우가 발생해 예상치 못한 값이 나옵니다. 파이썬의 int는 다릅니다:
# C에서 int 오버플로우 예시 (파이썬이 아닌 개념 설명)
# int x = 2147483647; (32비트 최대값)
# x + 1 → -2147483648 (오버플로우!)
# 파이썬에서는 오버플로우가 없음
x = 2 ** 31 - 1 # 32비트 최대값
print(x) # 2147483647
print(x + 1) # 2147483648 — 정확히 계산됨
# 어마어마하게 큰 수도 정확히 계산
big = 2 ** 1000
print(big) # 302자리 숫자가 출력됨
print(len(str(big))) # 302
# 암호학에서 사용하는 큰 소수 연산도 정확히 계산
prime = 2 ** 127 - 1 # 메르센 소수 (39자리)
print(prime)
파이썬의 정수가 임의 정밀도를 지원하는 이유는 내부 표현 방식에 있습니다. CPython의 PyLongObject는 정수를 30비트 단위(digit)의 배열로 저장합니다. 숫자가 커질수록 배열이 길어지는 방식입니다. 마치 종이에 긴 수를 손으로 쓰는 것처럼, 자릿수가 늘어나도 정확하게 표현됩니다.
단, 큰 정수 연산은 느립니다. 2 ** 1_000_000 같은 연산은 시간이 걸립니다. 시간 복잡도는 자릿수에 비례합니다.
💾 소형 정수 캐싱과 메모리
import sys
# 소형 정수 캐싱 (-5 ~ 256)
a = 100; b = 100
print(a is b) # True — 같은 캐시된 객체
a = 1000; b = 1000
print(a is b) # False — 새로운 객체 생성
# 정수 객체의 메모리 크기
print(sys.getsizeof(0)) # 24 bytes (작은 정수)
print(sys.getsizeof(10**100)) # 72 bytes (100자리 정수 — 더 큰 공간)
# 다양한 정수 리터럴
dec = 1_000_000 # 가독성을 위한 밑줄 (숫자값에는 영향 없음)
binary = 0b1010 # 2진수 → 10진수 10
octal = 0o17 # 8진수 → 10진수 15
hexa = 0xFF # 16진수 → 10진수 255
print(dec, binary, octal, hexa) # 1000000 10 15 255
# 진법 변환
print(bin(42)) # 0b101010
print(oct(42)) # 0o52
print(hex(42)) # 0x2a
print(int("101010", 2)) # 2진수 문자열 → 10진수 42
print(int("2a", 16)) # 16진수 문자열 → 10진수 42
⚙️ 비트 연산자 완전 정복
비트 연산은 CPU가 가장 빠르게 처리할 수 있는 연산입니다. 저수준 프로그래밍, 암호학, 성능 최적화에서 자주 사용됩니다:
a = 0b1010 # 10진수 10
b = 0b1100 # 10진수 12
# & (AND): 두 비트 모두 1일 때만 1
print(bin(a & b)) # 0b1000 (10진수 8)
# 1010
# 1100
# ----
# 1000
# | (OR): 두 비트 중 하나라도 1이면 1
print(bin(a | b)) # 0b1110 (10진수 14)
# ^ (XOR): 두 비트가 다를 때 1
print(bin(a ^ b)) # 0b0110 (10진수 6)
# ~ (NOT): 비트 반전 (2의 보수법: ~x = -(x+1))
print(~a) # -11
# << (왼쪽 시프트): 2를 곱하는 것과 동일
print(a << 1) # 20 (10 * 2)
print(a << 2) # 40 (10 * 4)
# >> (오른쪽 시프트): 2로 나누는 것과 동일 (정수 나눗셈)
print(a >> 1) # 5 (10 / 2)
print(a >> 2) # 2 (10 / 4, 버림)
비트 연산의 실용적인 활용:
# 1. 특정 비트가 켜져 있는지 확인 (비트 마스킹)
flags = 0b00001010 # 여러 상태를 비트로 표현
READ_FLAG = 0b00000001 # 비트 0
WRITE_FLAG = 0b00000010 # 비트 1
EXEC_FLAG = 0b00000100 # 비트 2
has_read = bool(flags & READ_FLAG) # False
has_write = bool(flags & WRITE_FLAG) # True
print(has_read, has_write)
# 2. 짝수/홀수 판별 (가장 빠른 방법)
def is_even(n):
return (n & 1) == 0
print(is_even(4)) # True
print(is_even(7)) # False
# 3. 두 수 교환 (XOR 트릭)
x, y = 5, 10
x ^= y # x = x ^ y
y ^= x # y = y ^ x
x ^= y # x = x ^ y
print(x, y) # 10, 5 — 임시 변수 없이 교환
# (실무에서는 a, b = b, a가 더 읽기 쉬움)
➗ 나눗셈 연산자의 함정
파이썬에서 나눗셈 관련 연산자는 세 가지입니다. 각각의 차이를 정확히 이해해야 합니다:
# / : 진짜 나눗셈 (항상 float 반환)
print(10 / 3) # 3.3333...
print(6 / 2) # 3.0 (나눠 떨어져도 float!)
print(type(6 / 2)) # <class 'float'>
# // : 바닥 나눗셈 (floor division, 정수 반환)
print(10 // 3) # 3 (소수점 버림이 아닌 바닥 방향)
print(-7 // 2) # -4 (주의! -3이 아님!)
# -7 / 2 = -3.5, floor(-3.5) = -4 (음수 방향)
# % : 나머지 (modulo)
print(10 % 3) # 1
print(-7 % 2) # 1 (수학적 정의: a = (a//b)*b + (a%b))
# -7 = (-4)*2 + 1 → 나머지 1
# divmod: 몫과 나머지를 동시에
quotient, remainder = divmod(10, 3)
print(quotient, remainder) # 3 1
# ** : 거듭제곱
print(2 ** 10) # 1024
print(2 ** -1) # 0.5 (음수 지수 → float)
print(2 ** 0.5) # 1.4142... (제곱근 → float)
# pow(base, exp, mod): 3인수 형태 (모듈러 거듭제곱)
# pow(2, 1000, 100)은 2^1000 mod 100 = ?
# 중간에 엄청나게 큰 수를 만들지 않고 효율적으로 계산
print(pow(2, 1000, 100)) # 76 (암호학에서 자주 사용)
-7 // 2 = -4인 이유를 이해하는 것이 중요합니다. 파이썬의 //는 C 언어의 정수 나눗셈(truncation toward zero)과 다릅니다. 파이썬은 수학적으로 정확한 바닥 함수(floor function)를 사용합니다. -7 / 2 = -3.5이고, -3.5의 바닥(바닥 방향 무한대)은 -4입니다. 이로 인해 a % b의 부호가 항상 b의 부호와 같다는 수학적 일관성이 유지됩니다.
⚠️ 자주 하는 실수
- / 와 // 혼동: 정수 결과가 필요한데
/를 쓰면 float이 나옵니다. 반복 횟수, 인덱스 등 정수가 필요한 곳에는//를 사용하세요. - 음수 바닥 나눗셈 오해:
-7 // 2는 -3이 아니라 -4입니다. 음수에서//의 결과를 예측할 때 주의하세요. - 큰 정수 is 비교:
a = 1000; b = 1000; a is b는 False입니다. 정수 값 비교는 항상==를 사용하세요.
📝 정리 및 다음 강의 예고
- 파이썬 정수는 임의 정밀도 — CPython의 ob_digit 배열로 무한히 큰 수를 표현합니다.
- 소형 정수 캐싱: -5~256 범위는 CPython이 미리 생성해 재사용합니다.
- 비트 연산(&, |, ^, ~, <<, >>)은 CPU가 가장 빠르게 처리하는 연산입니다.
/는 항상 float,//는 바닥 방향 정수,%는 수학적 나머지를 반환합니다.
다음 강의: 부동소수점(float)의 진실을 파헤칩니다. 왜
0.1 + 0.2 != 0.3인지, IEEE 754 표준이 무엇인지, 그리고 금융 계산에서 어떻게 이 문제를 피하는지 배웁니다.
관련 주제
- 임의 정밀도 정수
- 정수 캐싱(-5~256)
- 비트 연산자
- 진법 리터럴(2진·8진·16진)
- 바닥 나눗셈(//)
- divmod·pow 3인수
- 개발·프로그래밍
- 개발·프로그래밍 강의
- 파이썬 기초 40강 — 처음 배우는 프로그래밍
- 무료강의
- 무료 온라인 강의
- NUGUNA
- 누구나
