소스 코드:
모듈은 빠르고 정확하게 자리 올림 하는 십진 부동 소수 산술을 지원합니다. 데이터형보다 다음과 같은 몇 가지 장점을 제공합니다:
Decimal “은 사람을 염두에 두고 설계된 부동 소수점 모델에 기반하고, 필연적으로 최고 원리를 갖습니다 – 컴퓨터는 사람들이 학교에서 배우는 산술과 같은 방식으로 동작하는 산술을 반드시 제공해야 한다.” – 십진 산술 명세에서 발췌.
Decimal 수는 정확하게 표현할 수 있습니다. 반면에, 과 와 같은 수는, 이진 부동 소수점으로 정확히 표현할 수 없습니다. 최종 사용자는 일반적으로 이진 부동 소수점에서 그러하듯이 가 처럼 표시되는 것을 기대하지 않을 것입니다.
정확성은 산술에서도 유지됩니다全球排名第一오피스타포털의 주소. 십진 부동 소수점에서, 는 정확하게 0과 같습니다. 이진 부동 소수점에서, 결과는 입니다. 0에 가깝지만, 차이가 신뢰할 수 있는 동등성 검사를 방해하고, 차이는 누적 될 수 있습니다. 이러한 이유로, 강한 동등성 불변 조건을 갖는 회계 응용 프로그램에서는 decimal이 선호됩니다.
decimal 모듈은 유효 자릿수의 개념을 포함하고 있으므로 은 입니다. 후행 0은 유효성을 나타내기 위해 유지됩니다. 이것은 화폐 응용에서는 관례적인 표현입니다. 곱셈의 경우, “교과서” 접근법은 피승수의 모든 숫자를 사용합니다. 예를 들어 는 이고, 은 입니다.
하드웨어 기반 이진 부동 소수점과는 달리, decimal 모듈은 사용자가 변경할 수 있는 정밀도(기본값은 28자리)를 가지며, 주어진 문제에 따라 필요한 만큼 커질 수 있습니다:
이진 및 십진 부동 소수점 모두 출판된 표준에 따라 구현됩니다. 내장 float 형이 기능의 적당한 부분만을 드러내지만, decimal 모듈은 표준의 모든 필수 부분을 노출합니다. 필요한 경우, 프로그래머는 자리 올림(rounding) 및 신호(signal) 처리를 완전히 제어할 수 있습니다. 여기에는 정확하지 않은 연산을 차단하기 위한 예외를 사용하여 정확한 산술을 강제하는 옵션이 포함됩니다.
decimal 모듈은 “편견 없이, (때로 고정 소수점 산술이라고도 불리는) 정확한 자리 올림 없는 십진 산술과 자리 올림 있는 부동 소수점 산술을 모두” 지원하도록 설계되었습니다. – 십진 산술 명세에서 발췌.
모듈 설계의 중심 개념은 세 가지입니다: 십진수, 산술을 위한 컨텍스트, 신호(signal).
decimal 수는 불변입니다. 부호(sign), 계수(coefficient digits) 및 지수(exponent)로 구성됩니다. 유효성을 유지하기 위해, 계수는 후행 0을 자르지 않습니다. Decimal은 또한 , , 과 같은 특별한 값을 포함합니다. 표준은 또한 을 과 구별합니다.
산술 컨텍스트는 정밀도, 자리 올림 규칙, 지수에 대한 제한, 연산 결과를 나타내는 플래그 및 신호가 예외로 처리될지를 결정하는 트랩 활성화기(trap enabler)를 지정하는 환경입니다. 자리 올림 옵션에는 , , , , , , 및 가 있습니다.
신호는 계산 과정에서 발생하는 예외적인 조건의 그룹입니다. 응용 프로그램의 필요에 따라, 신호가 무시되거나, 정보로 간주하거나, 예외로 처리될 수 있습니다. decimal 모듈의 신호는 , , , , , , , , 입니다.
각 신호에는 플래그와 트랩 활성화기가 있습니다. 신호와 만났을 때, 플래그가 1로 설정되고 트랩 활성화기가 1로 설정된 경우, 예외가 발생합니다. 플래그는 상태가 유지되므로(sticky) 계산을 감시하기 전에 재설정할 필요가 있습니다.
decimal을 사용하는 일반적인 시작은 모듈을 임포트하고, 로 현재 컨텍스트를 보고, 필요하다면 정밀도, 자리 올림 또는 활성화된 트랩에 대해 새 값을 설정하는 것입니다:
Decimal 인스턴스는 정수, 문자열, 실수(float) 또는 튜플로 만들 수 있습니다. 정수 나 실수로 만들면 해당 정수 또는 실수의 정확한 값 변환이 일어납니다. Decimal 수는 “숫자가 아님(Not a number)”을 나타내는 , 양과 음의 및 과 같은 특수한 값을 포함합니다:
신호를 트랩 하는 경우, 실수로 생성자나 대소비교에서 Decimal 수와 실수(float)를 혼합하면 예외가 발생합니다:
새로운 Decimal의 유효 숫자는 입력된 숫자의 개수에 의해서만 결정됩니다. 컨텍스트 정밀도 및 자리 올림은 오직 산술 연산 중에만 작용합니다.
C 버전의 내부 제한을 초과하면, Decimal 을 만들 때 를 일으킵니다:
Decimal은 파이썬의 다른 부분들과 잘 어울립니다. 다음은 십진 부동 소수점으로 부린 작은 묘기입니다:
그리고 Decimal에는 몇 가지 수학 함수도 있습니다:
메서드는 숫자를 고정된 지수로 자리 올림 합니다. 이 방법은 종종 결과를 고정된 자릿수로 자리 올림 하는 화폐 응용에 유용합니다.:
위에서 보듯이, 함수는 현재 컨텍스트에 액세스하고 설정을 변경할 수 있게 합니다. 이 방법은 대부분 응용 프로그램의 요구를 충족시킵니다.
고급 작업을 위해, Context() 생성자를 사용하여 대체 컨텍스트를 만드는 것이 유용할 수 있습니다. 대체 컨텍스트를 활성화하려면, 함수를 사용하십시오.
표준에 따라, 모듈은 당장 사용할 수 있는 두 개의 표준 컨텍스트 와 를 제공합니다. 특히 전자는 많은 트랩이 활성화되어있어 디버깅에 유용합니다:
컨텍스트에는 계산 중에 발생하는 예외 조건을 감시하기 위한 신호 플래그도 있습니다. 플래그는 명시적으로 지워질 때까지 설정된 상태로 유지되므로, 메서드를 사용하여 모니터링되는 각 계산 집합 앞에서 플래그를 지우는 것이 가장 좋습니다.
flags 엔트리는 에 대한 유리수 근삿값이 자리 올림 되었고 (컨텍스트 정밀도 이상의 숫자가 버려졌습니다) 결과가 부정확하다는 (폐기된 숫자 일부는 0이 아닙니다) 것을 보여줍니다.
개별 트랩은 컨텍스트의 필드에 있는 딕셔너리를 사용해서 설정합니다.:
대부분 프로그램은 프로그램 시작 시에 한 번만 현재 컨텍스트를 조정합니다. 그리고, 많은 응용 프로그램에서, 데이터는 루프 내에서 단일형변환으로 로 변환되어, 프로그램 대부분은 다른 파이썬 숫자 형과 별로 다르지 않게 데이터를 조작합니다.
, , 와 메서드는 인자가 논리적 피연산자 이길 기대합니다. 논리적 피연산자 는 全球排名第一오피스타 지수와 부호가 모두 0이고 숫자는 모두 또는 인 인스턴스입니다.
컨텍스트는 산술 연산을 위한 환경입니다. 정밀도를 제어하고, 자리 올림 규칙을 설정하며, 어떤 신호가 예외로 처리되는지 결정하고, 지수의 범위를 제한합니다.
각 스레드는 자신만의 현재 컨텍스트를 가지는데, 와 함수를 사용하여 액세스하거나 변경합니다:
또한 문과 함수를 사용하여 활성 컨텍스트를 일시적으로 변경할 수 있습니다.
아래에 설명된 생성자를 사용하여 새로운 컨텍스트를 만들 수도 있습니다. 또한, 이 모듈은 세 가지 미리 만들어진 컨텍스트를 제공합니다:
3개의 제공된 컨텍스트 외에도, 새로운 컨텍스트를 생성자를 사용하여 만들 수 있습니다.
이 절의 상수는 C 모듈에서만 의미가 있습니다. 호환성을 위해 순수 파이썬 버전에도 포함되어 있습니다.
신호는 계산 중 발생하는 조건을 나타냅니다. 각각은 하나의 컨텍스트 플래그와 하나의 컨텍스트 트랩 활성화기에 대응합니다.
컨텍스트 플래그는 조건이 발생할 때마다 설정됩니다. 계산 후에, 플래그는 정보를 얻기 위한 목적으로 확인될 수 있습니다 (예를 들어, 계산이 정확한지를 판별하기 위해). 플래그를 확인한 후 다음 계산을 시작하기 전에 모든 플래그를 지우십시오.
컨텍스트의 트랩 활성화기가 신호에 대해 설정되면, 조건은 파이썬 예외를 일으킵니다. 예를 들어, 트랩이 설정되면, 이 조건을 만날 때 예외가 발생합니다.
다음 표는 신호의 계층 구조를 요약한 것입니다:
십진 부동 소수점을 사용하면 십진수 표현 오차가 없어집니다 (을 정확히 나타낼 수 있습니다); 그러나 0이 아닌 숫자가 고정된 정밀도를 초과할 때 일부 연산은 여전히 자리 올림 오차를 일으킬 수 있습니다.
자리 올림 오차의 효과는 거의 상쇄되는 양을 더하거나 빼는 것에 의해 증폭되어 유효숫자의 손실로 이어질 수 있습니다. Knuth는 불충분한 정밀도로 자리 올림 된 부동 소수점 산술로 인해 덧셈의 결합 법칙과 배분 법칙이 파괴되는 두 가지 사례를 제공합니다:
모듈은 유효숫자의 손실을 피할 수 있을 만큼 정밀도를 확장함으로써 항등 관계를 복구할 수 있게 합니다 :
모듈의 수 체계는 , , , 와 두 개의 0 과 을 포함하는 특수 값을 제공합니다.
무한대는 다음과 같이 직접 생성될 수 있습니다: . 또한, 신호가 트랩 되지 않을 때 0으로 나눠서 발생할 수 있습니다. 마찬가지로, 신호가 트랩 되지 않을 때, 무한대는 표현 가능한 가장 큰 수의 한계를 넘어서 자리 올림 된 결과가 될 수 있습니다.
무한대는 부호가 있고 (아핀) 산술 연산에 사용될 수 있는데, 매우 크고 불확정적(indeterminate)인 숫자로 취급됩니다. 예를 들어, 무한대에 상수를 더하면 또 다른 무한대를 줍니다.
어떤 연산은 불확정적이고, 을 반환하거나, 신호가 트랩 되면, 예외를 발생시킵니다. 예를 들어, 은 “숫자가 아님(not a number)”을 의미하는 을 반환합니다. 이 종류의 은 조용하고, 한 번 만들어지면 다른 연산에 포함될 때 항상 다른 을 생성합니다. 이 동작은 때때로 빠진 입력이 있는 일련의 계산에 유용할 수 있습니다 — 특정 결과를 잘못된 것으로 표시하면서 계산을 진행할 수 있도록 합니다.
다른 종류는 인데, 모든 연산 후에 조용히 남아 있는 대신 신호를 줍니다. 이것은 유효하지 않은 결과가 특수한 처리를 위해 계산을 중단시켜야 할 때 유용한 반환 값입니다.
파이썬의 비교 연산자의 동작은 이 관련되어있을 때 약간 의외일 수 있습니다. 피연산자 중 하나가 조용하거나 신호를 주는 일 때, 같음 검사는 항상 를 반환하고 (심지어 조차도), 다름 검사는 항상 를 반환합니다. , , 또는 연산자 중 하나를 사용하여 두 Decimal을 비교하려는 시도는 피연산자 중 어느 것이 든 이면 신호를 발생시킵니다. 이 신호가 트랩 되지 않으면 를 반환합니다. 일반 십진 산술 명세는 직접 비교의 동작을 명시하지 않습니다; 을 포함하는 비교를 위한 이러한 규칙은 IEEE 854 표준(섹션 5.7의 표 3을 보세요)에서 가져온 것입니다. 엄격한 표준 준수를 위해서는, 대신 및 메서드를 사용하십시오.
부호 있는 0은 언더플로 하는 계산의 결과일 수 있습니다. 계산을 더 정밀하게 수행한다면 얻게 될 결과의 기호를 유지합니다. 크기가 0이기 때문에, 양과 음의 0은 같다고 취급되며 부호는 정보 용입니다.
서로 다른 부호를 갖는 부호 있는 0이 같은 것에 더해, 여전히 동등한 값이지만 다른 정밀도를 갖는 여러 표현이 존재합니다. 익숙해지는데 약간 시간이 필요합니다. 정규화된 부동 소수점 표현에 익숙한 사람들에게는, 다음 계산이 0과 같은 값을 반환한다는 것이 즉시 명백하지는 않습니다:
함수는 스레드마다 다른 객체에 접근합니다. 별도의 스레드 컨텍스트를 갖는다는 것은 스레드가 다른 스레드를 방해하지 않고 변경할 수 있음을 의미합니다 (가령 ).
마찬가지로, 함수는 자동으로 대상을 현재 스레드에 할당합니다.
가 전에 호출되지 않았다면, 는 현재 스레드에서 사용할 새로운 컨텍스트를 자동으로 생성합니다.
새 컨텍스트는 DefaultContext 라는 프로토타입 컨텍스트에서 복사됩니다. 각 스레드가 응용 프로그램 전체에서 같은 값을 사용하도록 기본값을 제어하려면, DefaultContext 객체를 직접 수정하십시오. 를 호출하는 스레드 사이에 경쟁 조건이 없도록, 어떤 스레드가 시작되기 전에 수행되어야 합니다. 예를 들면:
다음은 유틸리티 함수로 사용되고 클래스로 작업하는 방법을 보여주는 몇 가지 조리법입니다:
Q. 라고 입력하는 것은 귀찮은 일입니다. 대화형 인터프리터를 사용할 때 타자를 최소화할 방법이 있습니까?
A. 일부 사용자는 생성자를 하나의 문자로 축약합니다:
Q. 소수점 두 자리의 고정 소수점 응용 프로그램에서, 일부 입력에 여러 자리가 있고 자리 올림 해야 합니다. 어떤 것은 여분의 자릿수가 없다고 가정되지만, 유효성 검사가 필요합니다. 어떤 방법을 사용해야 합니까?
A. 메서드는 고정된 소수 자릿수로 자리 올림 합니다. 트랩이 설정되면, 유효성 검사에도 유용합니다:
Q. 일단 유효한 두 자리 입력이 있으면, 응용 프로그램 전체에서 해당 불변성을 어떻게 유지합니까?
A. 정수로 더하기, 빼기 및 곱하기와 같은 일부 연산은 고정 소수점을 자동으로 보존합니다. 나눗셈과 정수가 아닌 수로 곱하는 것과 같은 다른 연산은, 소수점 이하 자릿수를 바꿀 것이고, 뒤에 단계를 적용할 필요가 있습니다:
고정 소수점 응용 프로그램을 개발할 때, 단계를 처리하는 함수를 정의하는 것이 편리합니다:
Q. 같은 값을 표현하는 여러 가지 방법이 있습니다. 숫자 , , , 그리고 는 모두 다양한 정밀도로 같은 값을 가집니다. 이것들은 단일하게 인식할 수 있는 표준적인 값으로 변환할 방법이 있습니까?
A. the 메서드는 모든 해당 값을 단일 표현으로 매핑합니다:
Q. 일부 십진수 값은 항상 지수 표기법으로 인쇄됩니다. 지수가 아닌 표현을 얻을 방법이 있습니까?
A. 일부 값의 경우, 지수 표기법만이 계수에 있는 유효 숫자를 나타낼 수 있습니다. 예를 들어 을 으로 표현하면 값은 일정하게 유지되지만, 원본의 두 자리 유효숫자를 표시할 수 없습니다.
응용 프로그램이 유효 숫자를 추적하는 데 신경 쓰지 않으면, 지수 및 후행 0을 제거하고 유효숫자를 잃지만, 값이 바뀌지 않도록 하기는 쉽습니다:
Q. 일반 float를 로 변환하는 방법이 있습니까?
A. 그렇습니다. 모든 이진 부동 소수점은 Decimal로 정확히 표현될 수 있습니다. 하지만 정확한 변환이 취하는 정밀도는 직관이 제안하는 것보다 더 클 수 있습니다:
Q. 복잡한 계산에서, 정밀도가 부족하거나 자리 올림 이상이 발생하여 엉터리 결과를 얻지는 않았는지 확인하려면 어떻게 해야 합니까?
A. decimal 모듈은 결과를 쉽게 테스트할 수 있게 합니다. 가장 좋은 방법은 더 높은 정밀도와 다양한 자리 올림 모드를 사용하여 계산을 다시 실행하는 것입니다. 크게 다른 결과는 정밀도 부족, 자리 올림 모드 문제, 부적절한 입력 또는 수치가 불안정한 알고리즘을 나타냅니다.
컨텍스트 정밀도가 입력이 아닌 연산 결과에 적용된다는 사실을 확인했습니다. 다른 정밀도의 값을 혼합할 때 주의해야 할 것이 있습니까?
A. 그렇습니다. 원칙은 모든 값이 정확한 것으로 간주하므로 해당 값에 대한 산술도 마찬가지라는 것입니다. 결과 만 자리 올림 됩니다. 입력에 대한 이점은 “입력하는 것이 얻는 것”이라는 것입니다. 단점은 입력값을 자리 올림 하는 것을 잊어버리면 결과가 이상하게 보일 수 있다는 점입니다:
해법은 정밀도를 높이거나 단항 플러스 연산을 사용하여 입력의 자리 올림을 강제 수행하는 것입니다:
다른 방법으로, 입력은 메서드를 사용하여 생성 시에 자리 올림 될 수 있습니다:
Q. CPython 구현은 커다란 수에서 빠릅니까?
A. Yes. In the CPython and PyPy3 implementations, the C/CFFI versions of
the decimal module integrate the high speed library for
arbitrary precision correctly-rounded decimal floating point arithmetic.
세계랭킹1위오피스타 uses
for medium-sized numbers and the
for very large numbers. However, to realize this performance gain, the
context needs to be set for unrounded calculations.