티스토리 뷰
십진법(decimal)모듈은 실수를 표현하기 위하여 float자료형보다 정확한 Decimal클래스를 제공한다.
>> 부동소수점 표현 방식 <<
컴퓨터에서 수치데이터를 표현하기 위하여 정수는 고정소수점방식(fixed point)을, 실수는 부동소수점(floating point)방식을 사용한다. 부동소수점 방식은 소수점의 위치를 고정하기 않고 그 위치를 나타내는 수를 따로 적는 방식으로, 유효숫자를 나타내는 가수(mantissa)와 소수점의 위치를 풀이하는 지수(exponent)로 나누어서 표현하며, '[가수]*[밑수][지수]'와 같은형태가 된다.
예를 들어 0.4를 밑수가 10인 부동소수점으로 나타내면 0.4*101가 된다. 또 밑수가 2인 경우 0.8*-1이 되며, 정규화 작업을 하면 1.6*2-2가 된다. 여기서 밑수를 동일한 값을 사용하도록 규정하면 '가수'와 '지수'만을 이용하여 실수를 나타낼수 있다.
컴퓨터 시스템은 일반적으로 이진법이 이용됙ㅣ에 밑수를 2로하고 부호를 나타내는 하나의 비트를 추가하여, 아래와 같이 세부분으로 나누어서 실수를 표현한다.
1 | 8 | 23 |
부호 | 지수부 | 가수부 |
이러한 방식으로 표현되기 때문에, 컴퓨터에서 부동소수점으로 표현된 수가 원래 실수를 정확히 나타내지 못하는 문제가 있다.
>>> 0.1 0.10000000000000001 >>> 1/3 0.3333333333333333 |
또한 부동소수점 연산의 결과도 항상 동일한 결과를 반환하지 않는다.
아래의 예제를 통해 덧셈연산의 결합법칙이 성립되지 않는것을 알수 있다.
>>> (1234.567 + 45.67844) + 0.0004 1280.2458399999998 >>> 1234.567 + (45.67844 + 0.0004) 1280.24584 |
이러한 부동소수점 연산의 본질적인 문제를 해결하고자 파이썬에서는 십진법(decimal)모듈을 지원한다.
십진법모듈은 float와 다르게 실수를 정확하게 표현할수 있으며, 양의 무한대(Infinity), 음의 무한대(-Infinity), NaN(Not a Number - 연산과정에서 잘못된 입력을 받음)도 표현할수 있다. 또한 소수점 자리의 정밀도도 조정할수 있기 때문에 매우 큰 정밀도를 요하는 연산에도 사용할수 있다.
>> Decimal 객체 생성 <<
십진법모듈에서는 Decimal객체를 이용하여 실수를 표현한다. Decimal객체는 value로 정수, 문자열, 튜플, Decimal객체를 인자로 받아서 생성된다.
생성자 : decimal.Decimal([value[, context]])
문자열은 부동소수점 형태로도 입력이 가능하며, 'Infinity', 'Inf'(무한대), '-Infinity', '-Inf'(음의 무한대), 'NaN'(Not a Number), '-0' 형태도 가능하다. 튜플형태로 입력되는 경우, 부호를 나타내는 정수(0: 양수, 1: 음수)와 유효숫자를 나타내는 튜플, 소수점 자리를 나타내는 정수가 순차적으로 온다.
-. Decimal객체생성 예제
>>> import decimal >>> decimal.Decimal(3) #정수 Decimal('3') >>> decimal.Decimal('1.1') #문자열 Decimal('1.1') >>> decimal.Decimal(str(1/7)) #문자열 Decimal('0.14285714285714285') >>> decimal.Decimal((0, (3, 1, 4), -2)) #튜플 Decimal('3.14') >>> decimal.Decimal("-Infinity") #음의 무한대 Decimal('-Infinity') >>> decimal.Decimal('-0') #음의 0 Decimal('-0') >>> decimal.Decimal('NaN') #NaN(Not a Number) Decimal('NaN') >>> d = decimal.Decimal((0, (3, 1, 4), -2)) #Decimal 객체 >>> decimal.Decimal(d) Decimal('3.14') |
>> Decimal객체를 이용한 연산 <<
Decimal객체는 int, float와 같은 내장 수치 자료형과 동일하게 모든 수치 연산과 내장함수의 인자로 전달이 가능하다.
아래는 두 Decimal객체간에 수치연산을 수행하는 예제이다.
>>> import decimal >>> a, b = decimal.Decimal('3.14'),decimal.Decimal('.04') >>> a + b Decimal('3.18') >>> a - b Decimal('3.10') >>> a * b Decimal('0.1256') >>> a / b Decimal('78.5') >>> a ** b Decimal('1.046832472577719248090395663') |
또한 Decimal객체간의 연산뿐만 아니라 내장 수치 자료형과 상호연산도 가능하며, 내장함수의 인자로 전달할수 있다.
>>> a = decimal.Decimal('3.14') >>> a * 3 Decimal('9.42') >>> divmod(a, 2) (Decimal('1'), Decimal('1.14')) >>> round(a, 1) Decimal('3.1') >>> int(a) 3 |
그외 max(), min(), sum()과 같은 내장함수의 인자로도 전달가능하다.
>>> rawData = '3.45|5.3|1.65|9|-1.28' >>> l = [decimal.Decimal(x) for x in rawData.split('|')] >>> l [Decimal('3.45'), Decimal('5.3'), Decimal('1.65'), Decimal('9'), Decimal('-1.28')] >>> max(l) #최댓값 Decimal('9') >>> min(l) #최솟값 Decimal('-1.28') >>> sum(l) #합계 Decimal('18.12') >>> sorted(l) #정렬 [Decimal('-1.28'), Decimal('1.65'), Decimal('3.45'), Decimal('5.3'), Decimal('9')] |
>> Decimal객체의 내장 메서드 <<
아래는 Decimal객체에서 지원하는 내장메서드중 주로 사용되는 것들이다.
>sqrt()
Decimal의 제곱근 결과를 반환
>>> import decimal >>> d = decimal.Decimal("3.14") >>> d.sqrt() Decimal('1.772004514666935040199112510') |
>exp()
자연상수(e) ** Decimal결과를 반환
>>> d.exp() Decimal('23.10386685872218278457908458') |
>ln()
Decimal의 자연로그 결과를 반환
>>> d.ln() Decimal('1.144222799920161998805694448') |
>compare(other)
두 Decimal객체를 비교하여 그 결과를Decimal객체로 반환
메서드 호출객체가 더 크면 Decimal('1')을, 같은 경우는 Decimal('0')을, 작은경우는 Decimal('-1')을 반환
>>> d2 = decimal.Decimal("-1.414") >>> d.compare(d2) Decimal('1') |
>copy_abs()
원본의 절대값을 갖는 Decimal객체를 반환
>>> d2.copy_abs() Decimal('1.414') |
>copy_negate()
원본의 음수값을 갖는 Decimal객체를 반환
>>> d.copy_negate() Decimal('-3.14') |
>copy_sign(other)
원본 값에 인자(other)의 부호를 갖는 Decimal객체를 반환
>>> d.copy_sign(d2) Decimal('-3.14') |
>is_signed()
부호 비트가 설정되어 있으면(즉 음수이면) True를 반환
>>> d2.is_signed() True |
>is_finite()
유한수인 경우 True반환
>>> d.is_finite() True |
>is_infinite()
무한인 경우 True반환
>>> d.is_infinite() False |
>is_zero()
'0'(+0, -0)인 경우 True반환
>>> d.is_zero() False |
>> Decimal객체의 설정 <<
아래와 같이 두 Decimal객체의 연산결과는 기본적으로 소수 28번째 자리까지 출력되는것을 확인할수 있다.
>>> import decimal >>> d = decimal.Decimal('3.14') >>> d2 = decimal.Decimal(7) >>> d / d2 Decimal('0.4485714285714285714285714286') |
그 이유는 현재 Decimal객체의 환경설정(context)이 그렇게 되어 있기 때문이다.
현재 환경설정은 getcontext()함수로 확인할수 있다.
>>> decimal.getcontext() Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[Inexact, Rounded], traps=[InvalidOperation, DivisionByZero, Overflow]) |
그럼 현재 Decimal객체의 환경설정을 변경해보도록 하겠다.
연산결과가 소수7번째 자리까지 되로록 설정해보겠다.
>>> decimal.getcontext().prec=7 >>> d/d2 Decimal('0.4485714') |
현재 설정은 소수8번째 자리에서 반올림하도록 되어있는데, 이를 올림 연산으로 변경하겠다.
연산결과 마지막 7번째 자리가 올림 연산으로 바뀐것을 확인할수 있다.
>>> decimal.getcontext().rounding = decimal.ROUND_CEILING >>> d / d2 Decimal('0.4485715') |
반올림 설정 값으로 사용될수 있는 옵션은 아래와 같은 것들이 있다.
ROUND_CEILING |
ROUND_DOWN |
ROUND_FLOOR |
ROUND_HALF_DOWN |
ROUND_HALF_EVEN |
ROUND_HALF_UP |
ROUND_UP |
ROUND_05UP |
다음으로 기본환경설정에서는 '0'으로 나누는 경우 ZeroDivisionError가 발생하도록 되어 있다. 환경설정을 변경하여 '0'으로 나누어도 에러가 발생하지 않고, 무한대의 값을 반환하도록 설정하겠다.
>>> d = decimal.Decimal("3.14") >>> d2 = decimal.Decimal() #Decimal('0') >>> d / d2 #ZeroDivisionError 발생 Traceback (most recent call last): File "<pyshell#102>", line 1, in <module> d / d2 File "C:\Python32\lib\decimal.py", line 1300, in __truediv__ return context._raise_error(DivisionByZero, 'x / 0', sign) File "C:\Python32\lib\decimal.py", line 3926, in _raise_error raise error(explanation) decimal.DivisionByZero: x / 0 >>> decimal.getcontext().traps[decimal.DivisionByZero] = 0 >>> d / d2 Decimal('Infinity') #연산결과 무한대로 나타남 |
decimal모듈에서는 자주 사용되는 환경설정에 대해서 미리 정의해두었다.
각 설정은 아래와 같다.
>>> decimal.DefaultContext Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow]) >>> decimal.BasicContext Context(prec=9, rounding=ROUND_HALF_UP, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, Clamped, Underflow, DivisionByZero, Overflow]) >>> decimal.ExtendedContext Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[], traps=[]) |
미리 정의된 환경설정은 setcontext()함수를 이용하여 변경할수 있다.
>>> decimal.getcontext() #현재의 Decimal환경설정 Context(prec=7, rounding=ROUND_CEILING, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[Inexact, DivisionByZero, Rounded], traps=[InvalidOperation, Overflow]) >>> decimal.setcontext(decimal.ExtendedContext) #환경설정 변경 >>> decimal.getcontext() #변경된 Decimal 환경설정 Context(prec=9, rounding=ROUND_HALF_EVEN, Emin=-999999999, Emax=999999999, capitals=1, clamp=0, flags=[], traps=[]) |
참조 : 빠르게 활용하는 파이썬3 프로그래밍
'Python' 카테고리의 다른 글
Python, 데이터베이스의 사용 (0) | 2016.05.19 |
---|---|
Python,module random [랜덤] (0) | 2016.05.19 |
Python,module fractions [분수] (0) | 2016.05.19 |
Python,module math [수학] (0) | 2016.05.17 |
Python,module datetime [날짜시간] (0) | 2016.05.17 |
- Total
- Today
- Yesterday
- 상수
- Excel
- FetchType
- fetch join
- highlightbackground
- apache
- activebackground
- onetomany
- command
- tkinter
- Java
- JPA
- 파이썬
- Linux
- vba
- Python
- borderwidth
- highlightthickness
- disabledforeground
- 리눅스
- activeforeground
- checkbutton
- Module
- indicatoron
- Composite Key
- Private
- 폼
- IdClass
- tkinter command & bind [명령어묶기와 사건묶기] Python
- ManyToOne
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |