파이썬에는 10진 부동 소수점(decimal floating point) 관련 작업을 수행하기 위한 Decimal 모듈이 내장되어 있습니다. 이 모듈은 일반 float 타입에서 발생할 수 있는 오차를 줄여, 올바르게 반올림된(rounded) 10진 산술 연산을 제공합니다.
Decimal 모듈을 사용하려면 먼저 표준 라이브러리에서 이를 임포트해야 합니다.
import decimal
참고로 decimal.Decimal(25.36)처럼 float 값을 그대로 넘기면 이진 부동 소수점 변환 과정에서 생긴 오차까지 함께 표현됩니다. 정확한 10진수를 다루려면 decimal.Decimal('25.36')처럼 문자열로 전달하는 것이 좋습니다.
이 글에서는 Decimal 모듈의 자주 사용되는 핵심 함수들을 예제 코드와 함께 살펴보겠습니다.
제곱근 함수 sqrt()와 지수 함수 exp()
sqrt() 메서드는 주어진 Decimal 객체의 제곱근을 계산합니다. exp() 메서드는 주어진 x에 대해 e^x 값을 Decimal 숫자로 반환합니다.
예제 코드
#sqrt()와 exp() 메서드 수행
import decimal
my_dec = decimal.Decimal(25.36)
print(my_dec)
#Decimal 숫자의 제곱근 구하기
print('Square Root is: ' + str(my_dec.sqrt()))
#Decimal 숫자에 대한 e^x 구하기
print('e^x is: ' + str(my_dec.exp()))실행 결과
25.3599999999999994315658113919198513031005859375 Square Root is: 5.035871324805668565859161094 e^x is: 103206740212.7314661465187086
로그 함수: ln()과 log10()
Decimal 모듈에는 여러 로그 함수가 포함되어 있으며, 그중 대표적인 두 가지를 살펴보겠습니다. 첫 번째는 ln() 메서드로, Decimal 숫자의 자연로그(natural logarithm)를 구합니다.
두 번째는 log10() 메서드로, 밑(base)이 10인 로그값을 계산합니다.
예제 코드
#ln()과 log10() 메서드 수행
import decimal
my_dec = decimal.Decimal(25.36)
print(my_dec)
#밑이 e인 로그값 구하기
print('ln(x) is: ' + str(my_dec.ln()))
#밑이 10인 로그값 구하기
print('log(x) is: ' + str(my_dec.log10()))실행 결과
25.3599999999999994315658113919198513031005859375 ln(x) is: 3.233173129569025152000878282 log(x) is: 1.404149249209695070459909761
as_tuple()과 fma() 메서드
as_tuple() 메서드는 Decimal 숫자를 세 개의 요소를 가진 튜플로 표현합니다. 요소는 각각 부호(sign), 자릿수(digits), 지수(exponent)입니다. sign 값이 0이면 양수, 1이면 음수를 의미합니다.
fma() 메서드는 융합 곱셈-덧셈(fused multiply and add)이라고도 불립니다. fma(x, y)를 호출하면 (숫자 * x) + y를 계산하는데, 이때 (숫자 * x) 부분은 중간에 반올림되지 않는다는 점이 특징입니다. 덕분에 중간 반올림 오차 없이 한 번에 결과를 얻을 수 있습니다.
예제 코드
#as_tuple()과 fma() 메서드 수행
import decimal
my_dec1 = decimal.Decimal(5.3)
print(my_dec1)
my_dec2 = decimal.Decimal(-9.23)
print(my_dec2)
#Decimal을 튜플로 출력
print('\nmy_dec1 as tuple: ' + str(my_dec1.as_tuple()))
print('\nmy_dec2 as tuple: ' + str(my_dec2.as_tuple()))
#융합 곱셈-덧셈 수행
print('\n(x*5)+8 is: ' + str(my_dec1.fma(5, 8)))실행 결과
5.29999999999999982236431605997495353221893310546875 -9.230000000000000426325641456060111522674560546875 my_dec1 as tuple: DecimalTuple(sign=0, digits=(5, 2, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 8, 2, 2, 3, 6, 4, 3, 1, 6, 0, 5, 9, 9, 7, 4, 9, 5, 3, 5, 3, 2, 2, 1, 8, 9, 3, 3, 1, 0, 5, 4, 6, 8, 7, 5), exponent=-50) my_dec2 as tuple: DecimalTuple(sign=1, digits=(9, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 2, 6, 3, 2, 5, 6, 4, 1, 4, 5, 6, 0, 6, 0, 1, 1, 1, 5, 2, 2, 6, 7, 4, 5, 6, 0, 5, 4, 6, 8, 7, 5), exponent=-48) (x*5)+8 is: 34.49999999999999911182158030
compare() 메서드
compare() 메서드는 두 Decimal 숫자를 비교합니다. 두 숫자가 같으면 0을 반환하고, 첫 번째 숫자가 더 크면 +1, 첫 번째 인자가 더 작으면 -1을 반환합니다.
예제 코드
#compare() 메서드 수행
import decimal
#두 값이 같은 경우 비교
print('Compare value: ' + str(decimal.Decimal(-5.3).compare(decimal.Decimal(-5.3))))
#첫 번째 값이 더 작은 경우 비교
print('Compare value: ' + str(decimal.Decimal(-5.3).compare(decimal.Decimal(9.26))))
#첫 번째 값이 더 큰 경우 비교
print('Compare value: ' + str(decimal.Decimal(-5.3).compare(decimal.Decimal(-13.25))))실행 결과
Compare value: 0 Compare value: -1 Compare value: 1
복사 관련 함수들
Decimal 숫자를 다른 Decimal 객체로 복사하는 몇 가지 메서드가 있습니다.
- copy_abs(): Decimal 숫자의 절댓값을 구합니다.
- copy_negate(): 원래 숫자의 부호를 반전(negate)한 값을 복사해 반환합니다.
- copy_sign(): 두 번째 인자의 부호를 가져와 첫 번째 인자에 적용한 값을 반환합니다.
예제 코드
#copy_abs(), copy_negate(), copy_sign() 수행
import decimal
my_dec = decimal.Decimal(-25.36)
print(my_dec)
#절댓값 복사
temp_dec = my_dec.copy_abs()
print('Absolute is: ' + str(temp_dec))
#음수 값 복사
my_dec = decimal.Decimal(7.26)
temp_dec = my_dec.copy_negate()
print('Negate of 7.26 is: ' + str(temp_dec))
#두 번째 인자의 부호를 첫 번째 인자에 적용
my_dec = decimal.Decimal(-25.36)
temp_dec = my_dec.copy_sign(decimal.Decimal(12.5))
print('Copy sign from second argument: ' + str(temp_dec))실행 결과
-25.3599999999999994315658113919198513031005859375 Absolute is: 25.3599999999999994315658113919198513031005859375 Negate of 7.26 is: -7.2599999999999997868371792719699442386627197265625 Copy sign from second argument: 25.3599999999999994315658113919198513031005859375
max()와 min() 메서드
max()와 min()은 매우 단순한 메서드로, 두 숫자 사이의 최댓값 또는 최솟값을 각각 찾아줍니다.
예제 코드
#max()와 min() 메서드 수행
import decimal
my_dec1 = decimal.Decimal(5.3)
print(my_dec1)
my_dec2 = decimal.Decimal(-9.23)
print(my_dec2)
#최솟값과 최댓값 출력
print('Minumum: ' + str(my_dec1.min(my_dec2)))
print('Maximum: ' + str(my_dec2.max(my_dec1)))실행 결과
5.29999999999999982236431605997495353221893310546875 -9.230000000000000426325641456060111522674560546875 Minumum: -9.230000000000000426325641456 Maximum: 5.299999999999999822364316060
지금까지 파이썬 Decimal 모듈의 대표적인 함수들을 살펴보았습니다. 금융 계산이나 정밀한 소수 연산이 필요한 프로그램에서 Decimal 모듈을 활용하면 float 타입의 오차 문제를 효과적으로 피할 수 있습니다.