- Published on
파이썬으로 10진수를 2진수로 변환하는 법 내장 함수부터 직접 구현까지
- Authors
- Name
- 스타차일드
- https://x.com/ETFBITX
서버 로그를 분석하다가 비트 플래그를 확인해야 하거나, 임베디드/네트워크 헤더를 다루며 특정 비트를 읽어야 하는 순간이 있습니다. 그런데 막상 10진수 → 2진수 변환을 하려면 표현 형식(접두사 0b, 자릿수 패딩, 음수 처리) 같은 자잘한 이슈가 계속 튀어나옵니다.
이 글에서는 파이썬에서 10진수를 2진수로 변환하는 방법을 내장 함수 → 포맷팅 → 직접 구현(알고리즘) 순서로 정리하고, 현업에서 자주 겪는 트러블슈팅과 베스트 프랙티스까지 함께 다룹니다.
참고로 파이썬에서는 문자열 처리/리스트 조작이 함께 등장하는 경우가 많습니다. 변환 결과를 정리하거나 중복을 제거해야 한다면, 예전에 정리한 글인 파이썬 리스트 중복 제거와 정렬을 한 번에 끝내는 실전 패턴도 같이 보면 흐름이 좋습니다.
가장 빠른 정답: bin()으로 변환하기
파이썬 표준 내장 함수 bin()은 정수를 2진수 문자열로 바꿔줍니다.
n = 13
print(bin(n)) # '0b1101'
0b 접두사 제거하기
보통 화면 출력이나 API 응답으로는 0b가 거슬립니다.
n = 13
b = bin(n)[2:]
print(b) # '1101'
음수 처리 주의
음수는 다음처럼 나옵니다.
print(bin(-13)) # '-0b1101'
bin(n)[2:] 같은 방식은 음수에서 깨집니다. 음수도 지원하려면 부호를 분리하세요.
n = -13
sign = '-' if n < 0 else ''
bits = bin(abs(n))[2:]
print(sign + bits) # '-1101'
출력 품질 올리기: format()과 f-string 포맷팅
bin()은 간단하지만, 자릿수 고정(패딩), 구분자, 대문자/소문자 스타일 같은 출력 요구가 생기면 포맷팅이 더 깔끔합니다.
기본 2진수 문자열 (b 포맷)
n = 13
print(format(n, 'b')) # '1101'
print(f"{n:b}") # '1101'
0으로 자릿수 맞추기 (zero-padding)
예: 8비트로 맞춰 출력하고 싶을 때
n = 13
print(f"{n:08b}") # '00001101'
0b 포함해서 출력하기 (# 옵션)
n = 13
print(f"{n:#b}") # '0b1101'
print(f"{n:#010b}") # '0b00001101'
#010b는 전체 길이를 10으로 맞추는데, 0b도 길이에 포함됩니다. 즉 0b + 8비트 = 총 10자.
비트 마스크/플래그 확인에 유용한 패턴
2진수 변환은 종종 특정 비트가 켜져 있는지 확인하려는 목적입니다. 이때는 문자열로 바꾸기보다 비트 연산이 더 정확하고 빠릅니다.
k번째 비트가 1인지 확인
def is_bit_set(n: int, k: int) -> bool:
return (n & (1 << k)) != 0
n = 13 # 1101
print(is_bit_set(n, 0)) # True (LSB)
print(is_bit_set(n, 1)) # False
print(is_bit_set(n, 2)) # True
print(is_bit_set(n, 3)) # True
여러 플래그를 2진수로 보기 좋게 출력
flags = [1, 2, 4, 8, 16]
for f in flags:
print(f, f"{f:08b}")
직접 구현으로 원리 이해하기: 나눗셈(몫/나머지) 알고리즘
면접이나 알고리즘 학습, 혹은 특정 포맷을 직접 제어해야 할 때는 변환 원리를 구현해보는 게 도움이 됩니다.
핵심은 다음과 같습니다.
n을 2로 나눈 나머지(n % 2)가 가장 오른쪽 비트(LSB)n // 2로 줄여가며 반복- 나머지를 역순으로 모으면 2진수
def dec_to_bin(n: int) -> str:
if n == 0:
return "0"
sign = '-' if n < 0 else ''
n = abs(n)
bits = []
while n > 0:
bits.append(str(n % 2))
n //= 2
return sign + ''.join(reversed(bits))
print(dec_to_bin(13)) # '1101'
print(dec_to_bin(0)) # '0'
print(dec_to_bin(-13)) # '-1101'
구현에서 자주 틀리는 포인트
- 0 처리: 반복문이 한 번도 돌지 않으므로 예외 처리 필요
- 음수 처리:
abs()로 변환 후, 부호를 마지막에 붙이기 - 역순 처리: 나머지는 LSB부터 나오므로 뒤집어야 함
고정 비트 폭(2의 보수)로 음수를 표현하고 싶다면
-13을 -1101로 출력하는 건 “부호+절댓값” 표기입니다. 하지만 시스템 프로그래밍에서는 종종 8비트/16비트 2의 보수 형태가 필요합니다.
예를 들어 8비트에서 -13은 11110011 입니다.
def to_twos_complement_bin(n: int, width: int) -> str:
mask = (1 << width) - 1
return format(n & mask, f"0{width}b")
print(to_twos_complement_bin(-13, 8)) # '11110011'
print(to_twos_complement_bin(13, 8)) # '00001101'
트러블슈팅: width를 안 주면 끝없이 길어지는 느낌
파이썬의 정수는 arbitrary precision(무한 정밀도)라서, 음수에 대해 단순히 bin()을 쓰면 2의 보수 폭이 고정되지 않습니다. 따라서 원하는 비트 폭(width)을 명시하고 마스크(& ((1<<width)-1))를 씌우는 게 정석입니다.
실전 베스트 프랙티스 정리
1) “그냥 변환”이면 format(n, 'b')
bin()은0b가 붙어 후처리가 잦음format()/f-string은 깔끔하게 비트 문자열만 얻기 좋음
bits = format(13, 'b') # '1101'
2) 바이트/헤더 다루면 패딩을 기본값으로
bits8 = f"{13:08b}" # '00001101'
3) 음수는 “표현 목적”을 먼저 결정
- 사람에게 보여주기:
-+ 절댓값 이진수 - 시스템 표현: 2의 보수 + 고정 폭
결론: 상황별로 가장 좋은 선택은 다르다
- 가장 간단한 변환:
bin(n)(단,0b포함) - 실무에서 가장 많이 쓰는 형태:
format(n, 'b')또는f"{n:b}" - 비트 폭 고정 출력:
f"{n:08b}",f"{n:#010b}" - 음수를 2의 보수로 표현:
n & ((1<<width)-1)후format() - 원리 학습/커스텀 제어: 나눗셈 알고리즘으로 직접 구현
10진수→2진수 변환은 단순해 보이지만, 출력 규격(접두사/패딩/음수/폭)이 들어오는 순간부터가 진짜 시작입니다. 위 패턴들을 상황에 맞게 골라 쓰면 변환 코드가 깔끔해지고, 디버깅도 훨씬 쉬워집니다.