파이썬 fractions 모듈 완전 정복 ✖️➗ — 유리수로 정확 계산하기
파이썬 fractions 모듈 완전 정복 ✖️➗
부동소수점(float)은 빠르지만 오차가 생길 수 있습니다.
fractions.Fraction은 유리수(분수) 기반으로 정확한 연산을 제공합니다.
비율, 혼합비, 레시피, 확률 계산처럼 정확한 비가 중요한 상황에서 매우 유용합니다.
1) 기본: Fraction 생성과 사칙연산
from fractions import Fraction
# 정수/문자열/튜플로 생성
a = Fraction(1, 3) # 1/3
b = Fraction("2/5") # 2/5
c = Fraction(7, 10) # 7/10
print(a + b) # 11/15
print(b * c) # 1/5
print(c - a) # 11/30
print(a / b) # 5/6
# 기약분수로 자동 정규화
print(Fraction(50, 100)) # 1/2
2) float → Fraction: limit_denominator() 활용
왜 복잡한 분모가 나오나요?
float는 이진 근사라서 정확한 0.1을 표현하지 못합니다.
그 값을 Fraction으로 바꾸면 아주 큰 분모가 생길 수 있습니다.
from fractions import Fraction
x = 0.1
fx = Fraction(x) # Fraction(3602879701896397, 36028797018963968) 같은 큰 분모!
print(fx)
# 사람이 쓰기 좋은 근사분수로 제한
fx_simplified = fx.limit_denominator(1000) # 분모 최대 1000으로 제한
print(fx_simplified) # 1/10
TIP: 센서 비율, 혼합비 등은 Fraction("3/20")처럼
처음부터 문자열/분자·분모로 생성하면 불필요한 오차를 피할 수 있습니다.
3) 실전 예제
3-1. 혼합비/레시피 스케일링
from fractions import Fraction
# 페인트 A:B = 3:7, 총 2.5L 만들기
ratio = Fraction(3, 10) # A의 비율(3/10), B는 7/10
total = Fraction(5, 2) # 2.5L = 5/2
a = ratio * total # 3/10 * 5/2 = 15/20 = 3/4 L
b = (1 - ratio) * total # 7/10 * 5/2 = 35/20 = 7/4 L
print(a, b) # 3/4 7/4 (정확한 분수 결과)
3-2. 확률 계산(의사결정)
from fractions import Fraction
# 빨강 2개, 파랑 3개 공에서 하나 뽑기
p_red = Fraction(2, 5)
p_blue = Fraction(3, 5)
# 두 번 뽑아 둘 다 빨강일 확률(복원 추출 가정)
p_two_red = p_red * p_red
print(p_two_red) # 4/25 (0.16 아님, '정확'히 4/25)
3-3. 평균도 정확하게 (가중 평균 포함)
from fractions import Fraction
scores = [Fraction(1, 3), Fraction(1, 2), Fraction(3, 4)]
avg = sum(scores, start=Fraction(0, 1)) / len(scores)
print(avg) # 19/36
# 가중 평균: 가중치 2,3,5
weights = [2, 3, 5]
weighted = sum(s*w for s, w in zip(scores, weights)) / sum(weights)
print(weighted) # 정확한 유리수
4) decimal vs fractions: 언제 무엇을?
- fractions: 정확한 비율/조합/확률/개수(정수 비) — 분수 형태가 본질인 문제.
- decimal: 소수 자릿수와 반올림 규칙이 중요한 금융/세금/회계.
# 두 접근의 의도 차이 예시
from fractions import Fraction
from decimal import Decimal, getcontext, ROUND_HALF_UP
# 비율 정확성(분수)
mix = Fraction(2, 3) + Fraction(1, 6) # 5/6
# 금액 반올림(소수)
getcontext().rounding = ROUND_HALF_UP
price = Decimal("1.235").quantize(Decimal("0.01")) # 1.24 (상업적 반올림)
5) 성능·주의사항 & TIP
- 분자/분모가 커질수록 연산 비용이 증가합니다. 큰 데이터셋엔
limit_denominator로 관리하세요.
- float → Fraction 변환은 가급적 피하고, 문자열·정수로 직접 생성하세요.
- 출력 시엔
float()로 바꿔 보여줄 수 있지만, 내부 계산은 Fraction으로 유지하세요.
요약
fractions.Fraction은 유리수 기반의 정확 계산을 제공
limit_denominator()로 사람이 쓰기 좋은 근사 분수를 손쉽게 얻음
- 혼합비/레시피, 확률, 정확 평균 등 비율이 핵심인 문제에 특히 적합
decimal은 소수 자릿수·반올림 규칙이 중요한 금융 문제에 추천
자주 묻는 질문(FAQ)
Q1. 이미 float로 계산했는데 정확하게 바꾸려면?
A. Fraction.from_float(x).limit_denominator(n)을 사용해 근사 분수를 구한 뒤 이후 연산은 분수로 진행하세요.
Q2. Fraction 결과를 소수로 보여주려면?
A. 표시할 때만 float()나 format을 쓰고, 내부 계산은 분수로 유지하는 것이 안전합니다.
더 보기: 정확한 소수 계산이 필요하면
decimal 모듈 글도 함께 참고하세요. (블로그 내 연관 글)
댓글
댓글 쓰기