2025. 2. 8. 18:06ㆍ소프트웨어/기초
정확도가 중요한 경우 어떻게 해결할까?
부동 소수점 연산은 정밀한 계산이 필요한 경우 작은 오차가 누적될 수 있어 문제를 일으킬 수 있습니다.
특히 금융 계산, 과학 연산, 데이터 분석 등에서 정확한 연산 결과가 필요할 때는 대체 방법이 필요합니다.
이를 해결하는 방법으로 정수 연산 활용, decimal 모듈 사용, fractions 모듈 사용 등이 있습니다.
1. 정수 연산을 활용하는 방법 (소수점 이동 후 계산)
부동 소수점 오차를 줄이는 가장 쉬운 방법 중 하나는 소수를 정수로 변환하여 연산하는 것입니다.
(1) 원리: 소수점을 이동하여 정수로 변환 후 계산
예를 들어, 10.25 + 3.75를 계산한다고 가정해 봅시다.
- 소수점을 없애고 정수로 변환
- 10.25 → 1025, 3.75 → 375 (소수점 2자리 이동)
- 정수 연산 수행
- 1025 + 375 = 1400
- 결과를 다시 소수로 변환
- 1400 → 14.00
이 방식은 정수 연산만 수행하므로, 부동 소수점 오차가 발생하지 않습니다.
⚠ 주의: 하지만 0.1 같은 숫자는 2진법에서 정확히 표현되지 않기 때문에, 정수 변환 과정에서도 오차가 발생할 수 있습니다.
예를 들어, 0.1 * 100을 계산하면 10.0이 아닌 10.000000000000002가 될 가능성이 있습니다.
(2) 정수 연산 활용 예제 (반올림 적용)
# 정수 연산을 활용한 소수 연산 (소수점 2자리 이동 후 반올림 적용)
def add_decimal_numbers(a, b, decimal_places):
factor = 10 ** decimal_places
int_a = int(round(a * factor)) # 반올림 적용
int_b = int(round(b * factor)) # 반올림 적용
result = (int_a + int_b) / factor
return result
# 예제
print(add_decimal_numbers(0.1, 0.2, 2)) # 출력: 0.3
✔️ 소수점 이동을 통해 정수 연산을 수행하여 정확한 결과를 얻음
✔️ round() 함수를 활용하여 초기 부동 소수점 오차를 줄임
(3) 정수 연산이 유용한 경우
✅ 금융 계산 (예: 가격, 세금 계산)
✅ 고정 소수점 연산이 필요한 경우 (예: 하드웨어에서 부동 소수점 지원이 없는 경우)
✅ 미세한 오차를 허용할 수 없는 경우
⚠ 정수 연산의 한계
- 0.1처럼 2진수에서 정확히 표현되지 않는 숫자는 변환 과정에서도 오차가 발생할 수 있음
- 정수 연산 방식은 소수점 이동 범위를 고려해야 하므로, 코드 구현이 번거로울 수 있음
2. decimal 모듈을 활용하는 방법 (정확한 소수 연산)
Python의 decimal 모듈은 10진법 그대로 연산할 수 있어, 부동 소수점 오차를 방지할 수 있습니다.
특히, 금융 계산과 같은 정확도가 중요한 연산에서 많이 사용됩니다.
(1) decimal 모듈 사용 예제
from decimal import Decimal, getcontext
# 소수점 30자리까지 정밀도 설정
getcontext().prec = 30
a = Decimal('0.1') # 문자열로 초기화 필수!
b = Decimal('0.2')
print(a + b) # 출력: 0.3 (정확한 값)
✔️ decimal을 사용하면 0.1과 0.2가 정확하게 저장되므로 오차가 발생하지 않음
✔️ Decimal(0.1)이 아닌, Decimal('0.1')을 사용해야 함 (부동 소수점 오차를 방지)
(2) decimal이 유용한 경우
✅ 금융 및 회계 연산 (예: 은행 시스템, 화폐 단위 계산)
✅ 과학 연산 및 실험 데이터 처리
✅ 부동 소수점의 오차를 허용할 수 없는 경우
⚠ decimal의 한계
- 연산 속도가 일반적인 부동 소수점보다 느리며, 메모리 사용량이 많음
- 1초에 수백만 건의 금융 연산이 필요한 경우, 성능 이슈 발생 가능
3. fractions 모듈을 활용하는 방법 (정확한 분수 연산)
fractions 모듈을 사용하면 소수를 분수(Fraction) 형태로 저장하여 부동 소수점 오차 없이 연산할 수 있습니다.
특히, 정확한 비율이나 비례 계산이 필요한 경우 매우 유용합니다.
(1) fractions 모듈 사용 예제
from fractions import Fraction
a = Fraction(1, 10) # 1/10 (0.1)
b = Fraction(2, 10) # 2/10 (0.2)
print(a + b) # 출력: 3/10
print(float(a + b)) # 출력: 0.3 (정확한 값)
✔️ fractions을 사용하면 정확한 값으로 연산 가능
(2) fractions이 유용한 경우
✅ 기하학적 계산 (예: 삼각형 비율 계산, 도형 비례 계산)
✅ 음악 이론 (예: 박자 계산, 음계 비율 계산)
✅ 수학적 연산 (예: 정확한 분수 연산이 필요한 경우)
⚠ fractions의 한계
- 무리수(π, e)는 정확하게 표현할 수 없음
- 큰 분모/분자를 사용하는 경우 연산 속도가 저하될 수 있음
from fractions import Fraction large_fraction = Fraction(123456789, 987654321) print(large_fraction) # 연산 속도 저하 가능성 있음
- 실수 연산과 혼합해서 사용할 경우 변환 과정 필요
4. 각 방법 비교 및 선택 기준
방법 | 장점 | 단점 | 추천 사용 사례 |
정수 연산 | 빠르고 효율적, 간단함 | 일부 숫자는 오차 발생 가능 | 금융, 가격 계산, 센서 데이터 |
decimal 모듈 | 높은 정밀도, 10진법 유지 | 속도가 느리고 메모리 사용 많음 | 금융, 과학 연산, 회계 |
fractions 모듈 | 정확한 비율 연산 가능 | 큰 숫자 연산 속도 저하 | 기하학, 음악, 수학 계산 |
5. 정리
✅ 정확한 계산이 필요한 경우, 부동 소수점 대신 정수 연산, decimal, fractions 모듈을 사용할 수 있다.
✅ 정수 연산은 빠르고 간단하지만, 0.1과 같은 숫자는 여전히 오차 발생 가능
✅ decimal 모듈은 10진법 그대로 유지하여 금융, 과학 연산에서 유용
✅ fractions 모듈은 정확한 분수 연산이 필요할 때 사용
'소프트웨어 > 기초' 카테고리의 다른 글
부동 소수점 - 6. 정리 및 실전 예제 (부동 소수점 & IEEE 754 표준) (0) | 2025.02.08 |
---|---|
부동 소수점 - 4. 부동 소수점 연산의 한계 (0) | 2025.02.08 |
부동 소수점 - 3. 부동 소수점 표기법 (IEEE 754 표준 개념) (0) | 2025.02.08 |
부동 소수점 - 2. 컴퓨터가 숫자를 표현하는 방식 (0) | 2025.02.08 |
부동 소수점 - 1. 부동 소수점이란? (0) | 2025.02.08 |