PEP 242 – 숫자 종류(Numeric Kinds)
- Author:
- Paul F. Dubois <paul at pfdubois.com>
- Status:
- Withdrawn
- Type:
- Standards Track
- Created:
- 17-Mar-2001
- Python-Version:
- 2.2
- Post-History:
- 17-Apr-2001
Table of Contents
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 제안은 사용자가 원할 때 수치 계산의 정밀도와 범위를 직접 정할 수 있게 합니다. 따라서 계산을 한 번 작성해 두면 어디서 실행하든 적어도 원하는 정밀도와 범위가 보장됩니다. 이 제안은 기존 코드와의 하위 호환성을 유지합니다. 십진 리터럴의 의미도 명확해집니다.
근거
현재는 Fortran 90을 제외한 어떤 언어로도, 부동소수점을 사용하면서 플랫폼과 관계없이 대략 같은 답을 내는 프로그램을 이식 가능한 방식으로 작성할 수 없습니다. 그것이 불가능한 경우 컴파일을 거부하는 프로그램도 작성할 수 없습니다. 현재 Python에는 부동소수점 타입이 하나뿐이며, C 구현에서는 C의 double과 같습니다.
단정밀도(single) 또는 4배 정밀도(quad) 부동소수점에 해당하는 타입은 없습니다. 이런 타입을 언어에 직접 도입하면 언어가 복잡해지고, 도입한 뒤에도 그 타입을 사용하는 코드는 이식성이 없습니다. 이 제안은 Fortran 90의 “kind” 방식을 Python 환경에 맞게 고친 것과 비슷합니다. 이 기능을 사용하면 한 줄만 바꾸어 계산 전체의 정밀도 수준을 다른 수준으로 바꿀 수 있습니다. 원하는 정밀도를 지원하지 않는 기계에서는 프로그램이 틀린 답을 내지 않고 실패합니다. 이런 방식으로 코드를 작성하면 실패할 루틴을 초반에 호출하게 됩니다. 따라서 컴파일을 거부하는 것 다음으로 좋은 방법입니다.
지원되는 정수 및 부동소수점 종류
Python은 복소수 없이도 빌드할 수 있으므로 복소수는 아래에서 따로 다룹니다.
각 Python 컴파일러는 정수와 부동소수점 수의 “종류(kind)”를 원하는 만큼 정의할 수 있습니다. 다만 기존의 int와 long에 해당하는 정수 종류를 최소 두 가지 지원해야 하고, 현재의 float에 해당하는 부동소수점 수 종류를 최소 한 가지 지원해야 합니다.
이 필수 종류들의 범위와 정밀도는 지금처럼 프로세서에 따라 달라집니다. 단, 임의의 정수를 담을 수 있는 “long integer” 종류는 예외입니다.
내장 함수 int(), long(), float()는 지금처럼 입력을 이 기본 종류들로 변환합니다. (유니코드 문자열은 사실 다른 “종류”의 문자열이라는 점에 유의하십시오. 이 분야를 잘 아는 사람이라면 이 PEP를 확장해 그 경우까지 다룰 수 있을 것입니다.)
컴파일러는 각 타입(정수, 부동소수점)마다 선형 순서가 있는 종류들의 집합을 지원합니다. 순서는 더 넓은 범위나 더 높은 정밀도, 또는 둘 다를 갖춘 수를 담을 수 있는지에 따라 정해집니다.
종류 객체
“kinds”라는 이름의 모듈에 새로운 표준 함수 두 개가 정의됩니다. 이 함수들은 종류 객체(kind object)라는 호출 가능 객체를 반환합니다. 정수 또는 부동소수점 종류 객체 f의 시그니처는 result = f(x)이고, 복소수 종류 객체의 시그니처는 result = f(x, y=0.)입니다.
int_kind(n)- 정수 인자
n >= 1에 대해 호출 가능 객체를 반환합니다. 이 객체의 결과는 열린 구간 (-10**n,10**n) 안의 정수를 담을 수 있는 정수 종류입니다. 이 종류 객체는 long을 포함한 정수를 인자로 받습니다.n == 0이면 Python 리터럴 0에 해당하는 종류 객체를 반환합니다. float_kind(nd, n)nd >= 0이고n >= 1일 때, 정밀도가 최소 nd 자리이고 10진 지수가 닫힌 구간[-n, n]에 속하는 부동 소수점 수를 담을 수 있는 부동 소수점 kind를 결과로 내는 호출 가능 객체를 반환합니다. 이 kind 객체는 정수나 부동 소수점 수인 인자를 받습니다.nd와 n이 모두 0이면 Python 리터럴 0.0에 대응하는 kind 객체를 반환합니다.
컴파일러는 해당 타입에 사용할 수 있는 kind 중에서 원하는 특성을 가진 가장 작은 kind에 대응하는 kind 객체를 반환합니다. 주어진 구현에 원하는 특성을 가진 kind가 없으면 OverflowError 예외가 발생합니다. kind 함수는 인자를 대상 kind로 변환하지만, 결과가 대상 kind의 범위에 맞지 않으면 OverflowError 예외가 발생합니다.
호출 가능 객체로서의 동작 외에도, kind 객체에는 해당 kind의 특성을 나타내는 속성이 있습니다.
name은 kind의 이름입니다. 표준 kind의 이름은 int, long, double입니다.typecode는Numeric또는array모듈에서 이 kind의 배열을 만드는 데 사용하기에 적합한 한 글자 문자열입니다. 표준 타입의 typecode는 각각 ‘i’, ‘O’, ‘d’입니다.- 정수 kind에는 다음과 같은 추가 속성이 있습니다.
MAX는 이 kind에서 허용되는 최대 정수와 같으며, long kind의 경우None입니다.MIN은 이 kind에서 허용되는 가장 작은 음의 정수와 같으며, long kind의 경우None입니다. - 부동 소수점 kind에는 다음과 같은 추가 속성이 있으며, 그 값은 표준 헤더 파일 “float.h”에 있는 대응 C 타입의 해당 값과 같습니다.
MAX,MIN,DIG,MANT_DIG,EPSILON,MAX_EXP,MAX_10_EXP,MIN_EXP,MIN_10_EXP,RADIX,ROUNDS(float.h의FLT_RADIX,FLT_ROUNDS와 같음). 이 값들은MAX,MIN,EPSILON을 제외하고 정수 타입이며, 이 세 값은 해당 kind에 대응하는 Python 부동소수점 타입입니다.
kinds 모듈의 속성
int_kinds는 사용 가능한 정수 kind를 가장 낮은 kind부터 가장 높은 kind 순으로 정렬한 리스트입니다. 정의상 int_kinds[-1]은 long kind입니다.
float_kinds는 사용 가능한 부동 소수점 kind를 가장 낮은 kind부터 가장 높은 kind 순으로 정렬한 리스트입니다.
default_int_kind는 Python 리터럴 0에 대응하는 kind 객체입니다.
default_long_kind는 Python 리터럴 0L에 대응하는 kind 객체입니다.
default_float_kind는 Python 리터럴 0.0에 대응하는 kind 객체입니다.
복소수
복소수가 지원되는 경우, 복소수의 실수부와 허수부는 같은 kind의 부동 소수점 수입니다. Python 컴파일러가 복소수를 지원한다면, 지원하는 각 부동소수점 kind에 대응하는 복소수 kind도 지원해야 합니다.
복소수가 지원되는 경우, kinds 모듈에서 다음을 사용할 수 있습니다:
complex_kind(nd, n)- 각 구성 요소(.real, .imag)가
float_kind(nd, n)kind인 복소수를 담을 수 있는 복소수 kind를 결과로 내는 호출 가능 객체를 반환합니다. 이 kind 객체는 정수, 실수, 복소수 kind 중 어느 것이든 인자 하나를 받거나, 각각 정수나 실수인 인자 두 개를 받습니다.
complex_kinds는 사용 가능한 복소수 kind를 가장 낮은 kind부터 가장 높은 kind 순으로 정렬한 리스트입니다.
default_complex_kind는 Python 리터럴 0.0j에 대응하는 kind 객체입니다. 이 kind의 이름은 doublecomplex이며, typecode는 ‘D’입니다.
복소수 kind 객체에는 다음과 같은 추가 속성이 있습니다:
floatkind는 대응하는 float 타입의 kind 객체입니다.
예시
myprecision.py 모듈에서:
import kinds
tinyint = kinds.int_kind(1)
single = kinds.float_kind(6, 90)
double = kinds.float_kind(15, 300)
csingle = kinds.complex_kind(6, 90)
나머지 코드에서:
from myprecision import tinyint, single, double, csingle
n = tinyint(3)
x = double(1.e20)
z = 1.2
# builtin float gets you the default float kind, properties unknown
w = x * float(x)
# but in the following case we know w has kind "double".
w = x * double(z)
u = csingle(x + z * 1.0j)
u2 = csingle(x+z, 1.0)
이렇게 하면 myprecision.py의 인자만 바꿔서 코드 전체를 더 높은 정밀도로 바꿀 수 있다는 점에 주목하십시오.
참고: single != double이라는 보장은 없습니다. 하지만 double(1.e20)이 10진수 15자리의 정밀도와 10**300까지의 범위를 가진 수를 담거나, 그렇지 않으면 float_kind 호출이 실패한다는 것은 보장됩니다.
미해결 문제
현재까지 제기된 미해결 문제는 없습니다.
Copyright
This document has been placed in the public domain.