[Python] Number 자료형
동빈나 채널의 파이썬 문법 부수기 유튜브 강의를 참고하여 정리한 내용이다.
파이썬의 자료형 중에서 수(Number)를 다루는 정수형, 실수형, 복소수형에 대해 정리한다.
코딩테스트에서 실수 비교나 연산 연산자 관련 실수가 의외로 자주 나오는 부분이다.
파이썬 자료형 개요
파이썬의 주요 자료형은 아래와 같다.
| 자료형 | 설명 | 예시 |
|---|---|---|
| 정수형 | 소수점 없는 수 | 1, -5, 0 |
| 실수형 | 소수점 있는 수 | 3.14, -0.5, 1e9 |
| 복소수형 | 허수부 포함 | 3+4j, 1j |
| 문자열 | 텍스트 | "hello", '파이썬' |
| 리스트 | 순서 있는 가변 컬렉션 | [1, 2, 3] |
| 튜플 | 순서 있는 불변 컬렉션 | (1, 2, 3) |
| 사전 | 키-값 쌍 | {"a": 1, "b": 2} |
| 집합 | 중복 없는 컬렉션 | {1, 2, 3} |
이 중에서 이번 글에서는 수 자료형을 정리했다.
정수형 (int)
기본 사용
a = 1000
b = -7
c = 0
print(a) # 1000
print(b) # -7
print(c) # 0
print(type(a)) # <class 'int'>
파이썬에서 정수형의 크기 제한은 없다. 메모리가 허용하는 한 얼마든지 큰 수를 다룰 수 있다.
big = 2 ** 1000
print(big)
# 10715086071862673209484250490600018105614048117055336074437503883703510511249361...
C나 Java에서 long long의 최댓값(약 9.2 * 10^18)을 넘어가면 오버플로우가 나는 것과 다르다.
파이썬에서는 그냥 가능하다.
가독성을 위한 언더바(_)
# 언더바로 자릿수 구분 - 값에는 영향 없음
million = 1_000_000
billion = 1_000_000_000
print(million) # 1000000
print(billion) # 1000000000
print(million == 1000000) # True
큰 수를 다룰 때 쓰면 가독성이 좋아진다.
코딩테스트에서 1000000을 1_000_000으로 써도 아무 문제 없다.
실수형 (float)
기본 표현
a = 157.93
b = -1832.2
c = 5.
print(a) # 157.93
print(b) # -1832.2
print(c) # 5.0 - 소수점 뒤에 아무것도 없어도 5.0으로 인식
print(type(a)) # <class 'float'>
지수 표현 (e 표기법)
# 1e9 = 1 * 10^9 = 1000000000
a = 1e9
print(a) # 1000000000.0
print(type(a)) # <class 'float'> - 지수 표기는 float
# 코딩테스트에서 큰 수 초기화할 때 자주 씀
INF = float('inf') # 양의 무한대
print(INF) # inf
print(INF > 10**18) # True
# 지수 표기 예시
b = 75.25e1 # 75.25 * 10^1 = 752.5
c = 3.954e-3 # 3.954 * 10^-3 = 0.003954
print(b) # 752.5
print(c) # 0.003954
코딩테스트에서 무한대를 표현할 때 float('inf')나 1e9를 사용한다.
다익스트라나 최솟값 초기화에 자주 등장한다.
IEEE 754 부동소수점 오차
문제 상황
실수형을 다룰 때 가장 주의해야 할 부분이다.
a = 0.1 + 0.2
print(a) # 0.30000000000000004
print(a == 0.3) # False - 0.3이 아니다!
컴퓨터는 수를 2진수로 저장하는데, 0.1이나 0.2 같은 십진수 소수는 2진수로 정확하게 표현이 안 된다. 이걸 IEEE 754 부동소수점 오차라고 한다.
# 더 직관적으로 확인
print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 - 0.3) # 5.551115123125783e-17 (0이 아니다!)
round()로 해결
코딩테스트에서 실수 비교가 필요할 때는 round()를 사용해 반올림 후 비교한다.
a = 0.1 + 0.2
a = round(a, 2) # 소수점 둘째 자리로 반올림
print(a) # 0.3
print(a == 0.3) # True
# round() 기본 사용법
print(round(3.141592, 2)) # 3.14
print(round(3.141592, 4)) # 3.1416
print(round(3.5)) # 4 (반올림)
print(round(2.5)) # 2 - 파이썬은 banker's rounding (짝수 우선)
print(round(1234.5, -2)) # 1200.0 (음수는 정수 자리 반올림)
파이썬의
round()는 “사사오입” 방식이 아닌 banker’s rounding(은행 반올림)을 사용한다.round(2.5)는 3이 아니라 2가 나온다. 시험에 나오는 내용은 아니지만 알아두면 좋다.
math.isclose()로 정밀 비교
더 정밀한 비교가 필요하면 math.isclose()를 사용한다.
import math
a = 0.1 + 0.2
print(math.isclose(a, 0.3)) # True
# 허용 오차 직접 지정
print(math.isclose(a, 0.3, rel_tol=1e-9)) # True
print(math.isclose(a, 0.3001, abs_tol=1e-3)) # True (0.001 오차 허용)
수 자료형 연산
기본 연산자
a = 7
b = 3
print(a + b) # 10 (덧셈)
print(a - b) # 4 (뺄셈)
print(a * b) # 21 (곱셈)
print(a / b) # 2.3333333333333335 (나누기 - 항상 float 반환)
print(a // b) # 2 (몫 - 정수 나누기)
print(a % b) # 1 (나머지)
print(a ** b) # 343 (거듭제곱 - 7^3)
나누기 vs 몫 - 자주 헷갈리는 부분
# / 는 항상 float
print(10 / 5) # 2.0 (float)
print(10 / 3) # 3.3333333333333335 (float)
print(7 / 2) # 3.5 (float)
# // 는 정수 몫 (소수점 버림, int 반환)
print(10 // 5) # 2 (int)
print(10 // 3) # 3 (int)
print(7 // 2) # 3 (int)
# 음수 나눗셈 주의
print(-7 // 2) # -4 - 수학적으로 내림 (truncation이 아니라 floor)
print(-7 % 2) # 1 - 항상 양수 (나눗셈 후 나머지는 divisor 부호를 따름)
음수 나눗셈은 C나 Java와 다르게 작동한다. 파이썬의 //는 수학적 내림(floor)을 따르기 때문에 -7 // 2는 -3이 아니라 -4다. 코딩테스트에서 음수 인덱스나 음수 나눗셈을 다룰 때 주의한다.
# C 방식: -7 / 2 = -3 (0 방향으로 자름)
# Python 방식: -7 // 2 = -4 (음의 무한대 방향으로 자름)
import math
print(math.floor(-7 / 2)) # -4 (파이썬 // 와 동일)
print(int(-7 / 2)) # -3 (C 방식과 동일 - 소수점 버림)
거듭제곱
print(2 ** 10) # 1024
print(2 ** 32) # 4294967296
print(3 ** 3) # 27
# 제곱근은 ** 0.5
print(16 ** 0.5) # 4.0
print(9 ** 0.5) # 3.0
import math
print(math.sqrt(16)) # 4.0 - math.sqrt도 동일
연산자 우선순위
# ** 가 단항 - 보다 높은 우선순위를 가짐
print(-2 ** 2) # -4 - 2**2 먼저 계산 후 음수
print((-2) ** 2) # 4 - 괄호 먼저
# 헷갈리면 괄호를 명시적으로 쓰는 게 낫다
print(2 + 3 * 4) # 14 - 곱셈 먼저
print((2 + 3) * 4) # 20 - 괄호 먼저
형 변환
int ↔︎ float
# float → int (소수점 버림, 반올림 아님)
print(int(3.9)) # 3
print(int(-3.9)) # -3 (내림이 아닌 버림)
# int → float
print(float(3)) # 3.0
print(float(-5)) # -5.0
# 문자열 → 수
print(int("42")) # 42
print(float("3.14")) # 3.14
# 수 → 문자열
print(str(42)) # "42"
print(str(3.14)) # "3.14"
자주 하는 실수 : int() vs round()
# int()는 소수점을 버린다 (반올림 아님)
print(int(3.9)) # 3 (반올림이면 4가 되어야 하는데)
print(int(-3.2)) # -3 (음수에서 int는 0 방향으로 자름)
print(round(3.9)) # 4 (반올림)
print(round(-3.2)) # -3 (반올림)
# 문자열로 표현된 실수를 int()로 직접 변환하면 에러
print(int("3.14"))
# ValueError: invalid literal for int() with base 10: '3.14'
# 올바른 방법: 먼저 float으로 변환 후 int
print(int(float("3.14"))) # 3
수학 관련 내장 함수
# 절댓값
print(abs(-5)) # 5
print(abs(3.14)) # 3.14
# 최댓값, 최솟값
print(max(1, 5, 3)) # 5
print(min(1, 5, 3)) # 1
print(max([3, 1, 4, 1, 5, 9])) # 9
# 합계
print(sum([1, 2, 3, 4, 5])) # 15
# 거듭제곱 (모듈러 연산 포함)
print(pow(2, 10)) # 1024
print(pow(2, 10, 1000)) # 24 (2^10 % 1000, 큰 수 모듈러에 유용)
pow(base, exp, mod) 세 번째 인수로 모듈러를 넣으면 (base ** exp) % mod를 효율적으로 계산한다.
암호화 알고리즘이나 큰 수 나머지 문제에서 유용하다.
정리
- 파이썬 정수형은 크기 제한이 없다
- 실수형은 IEEE 754 부동소수점 오차 때문에 직접 비교(
==)를 피하고round()나math.isclose()를 사용한다 /는 항상 float,//는 몫(정수),%는 나머지- 음수 나눗셈에서
//는 floor 방향(음의 무한대 방향)으로 내림 int()는 반올림이 아니라 소수점 버림