Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

PEP 485 – 근사적 동등성 테스트를 위한 함수

Author:
Christopher Barker <PythonCHB at gmail.com>
Status:
Final
Type:
Standards Track
Created:
20-Jan-2015
Python-Version:
3.5
Post-History:

Resolution:
Python-Dev message

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

초록

이 PEP에서는 한 값이 다른 값과 대략적으로 같거나 “가까운지”를 판별하는 isclose() 함수를 표준 라이브러리 math 모듈에 추가할 것을 제안합니다.

근거

부동 소수점 값은 정밀도가 제한되어 있으므로 일부 값을 정확하게 표현할 수 없으며, 반복 계산을 수행하면 오류가 누적됩니다. 따라서 매우 특정한 상황에서만 동등성 비교를 사용하라는 조언이 일반적입니다. 부등식 비교로 해결되는 경우가 많지만, 계산된 값이 예상 값과 정확히 같을 필요 없이 “가까운지” 판별하려는 경우도 있습니다(테스트에서 흔히 그렇습니다). 특히 테스트에서 이러한 요구가 충분히 흔하고 그 방법이 항상 명확한 것은 아니므로, 표준 라이브러리에 이를 추가하면 유용할 것입니다.

기존 구현

표준 라이브러리에는 unittest.TestCase.assertAlmostEqual 메서드가 포함되어 있지만, 다음과 같은 단점이 있습니다.

  • unittest.TestCase 클래스 안에 묻혀 있습니다.
  • 어설션이므로 명령줄 등에서 일반적인 테스트로 쉽게 사용할 수 없습니다.
  • 절대 차이를 테스트합니다. 특히 부동 소수점 수에서는 차이를 측정할 때 절대 오차보다 상대 오차, 즉 “이 두 값은 서로 x% 이내인가?”가 필요한 경우가 많습니다. 특히 값의 크기를 사전에 알 수 없을 때 그렇습니다.

numpy 패키지에는 allclose()isclose() 함수가 있지만, numpy를 사용할 때만 이용할 수 있습니다.

statistics 패키지의 테스트에는 단위 테스트에 사용하는 구현이 포함되어 있습니다.

Stack Overflow 및 기타 도움말 사이트에서도 논의와 샘플 구현을 찾아볼 수 있습니다.

Boost C++ 라이브러리와 APL 언어 [4]를 비롯한 여러 비파이썬 시스템에서도 이러한 테스트를 제공합니다.

이러한 기존 구현은 이것이 일반적인 요구 사항이며 직접 작성하기가 사소하지 않음을 보여 주므로, 표준 라이브러리에 포함할 후보가 됩니다.

제안된 구현

참고: 이 PEP는 python-ideas 목록 [1]에서 진행된 장시간의 논의 결과입니다.

새 함수는 math 모듈에 추가되며, 다음과 같은 시그니처를 가집니다.:

isclose(a, b, rel_tol=1e-9, abs_tol=0.0)

ab는 상대적 근접성을 테스트할 두 값입니다.

rel_tol은 상대 허용 오차입니다. 즉, a 또는 b의 절댓값 중 더 큰 값에 상대적으로 허용되는 오류의 양입니다. 예를 들어 허용 오차를 5%로 설정하려면 tol=0.05를 전달하십시오. 기본 허용 오차는 1e-9이며, 두 값이 약 9자리의 십진 숫자 이내에서 같음을 보장합니다. rel_tol은 0.0보다 커야 합니다.

abs_tol은 최소 절대 허용 오차 수준이며, 0에 가까운 값을 비교할 때 유용합니다.

오류 검사 등을 제외하면, 이 함수는 다음의 결과를 반환합니다.:

abs(a-b) <= max( rel_tol * max(abs(a), abs(b)), abs_tol )

isclose라는 이름은 기존의 isnanisinf와 일관성을 유지하도록 선택되었습니다.

유한하지 않은 수 처리

IEEE 754의 특수 값 NaN, inf 및 -inf는 IEEE 규칙에 따라 처리됩니다. 구체적으로 NaN은 NaN을 포함한 어떤 다른 값과도 가까운 것으로 간주되지 않습니다. inf와 -inf는 자기 자신에 대해서만 가까운 것으로 간주됩니다.

부동 소수점이 아닌 형식

주요 사용 사례는 부동 소수점 수일 것으로 예상됩니다. 그러나 사용자는 다른 숫자 형식도 이와 유사하게 비교하려 할 수 있습니다. 이론적으로는 abs(), 곱셈, 비교 및 뺄셈을 지원하는 모든 형식에서 작동해야 합니다. 그러나 math 모듈의 구현은 C로 작성되어 있으므로, 파이썬의 덕 타이핑을 쉽게 사용할 수 없습니다. 대신 함수에 전달된 값은 계산이 수행되기 전에 float 형식으로 변환됩니다. 부동 소수점으로 변환할 수 없는 형식(또는 값)을 전달하면 적절한 예외(TypeError, ValueError 또는 OverflowError)가 발생합니다.

코드는 이러한 형식의 값 중 적어도 일부를 처리할 수 있도록 테스트됩니다.

  • Decimal
  • int
  • Fraction
  • complex: 복소수의 경우, cmath 모듈에 동반 함수가 추가됩니다. cmath.isclose()에서는 허용 오차가 부동 소수점 수로 지정되며, 크기 조정 및 비교에 complex 값의 절댓값이 사용됩니다. complex 허용 오차가 전달되면 그 절댓값이 허용 오차로 사용됩니다.

참고: 십진 형식에서 적절하고 완전하게 작동하는 Decimal.isclose()를 추가하는 것이 합리적일 수 있지만, 이는 이 PEP의 일부로 포함되지 않습니다.

0 근처에서의 동작

두 값 중 하나라도 0이면 상대 비교에 문제가 있습니다. 정의상 0에 비해 작은 값은 없습니다. 또한 계산상 두 값 중 하나가 0이면 차이는 다른 값의 절댓값이 되고, 계산된 절대 허용 오차는 rel_tol에 그 값을 곱한 값이 됩니다. rel_tol이 1보다 작으면 차이는 허용 오차보다 작아질 수 없습니다.

그러나 수학적으로는 정확하더라도, 계산된 값이 0에 “가까운지”를 알아야 하는 사용 사례가 많습니다. 이를 위해 절대 허용 오차 테스트가 필요합니다. 일부 예상 값만 0일 수 있는 루프나 컴프리헨션 내부에서 이 함수를 호출해야 하는 경우, 하나의 매개변수 집합을 사용하는 단일 함수로 상대 허용 오차와 절대 허용 오차를 모두 테스트할 수 있어야 합니다.

비교할 두 값이 0을 사이에 두고 있는 경우에도 비슷한 문제가 있습니다. a가 -b와 대략 같으면 a와 b는 결코 “가까운” 것으로 계산되지 않습니다.

이 경우를 처리하기 위해 선택적 매개변수인 abs_tol을 사용하여 계산된 상대 허용 오차가 매우 작거나 0인 경우에 사용할 최소 허용 오차를 설정할 수 있습니다. 즉, 두 값의 차이가 abs_tol보다 작으면 값은 항상 가까운 것으로 간주됩니다.

일반적인 경우에 적절한 값이 없으므로 기본 절대 허용 오차 값은 0으로 설정됩니다. 주어진 사용 사례에서 예상되는 값의 범위를 알지 못하면 적절한 값을 알아내는 것은 불가능합니다. 테스트하는 모든 값의 규모가 1 정도라면 약 1e-9의 값이 적절할 수 있지만, 예상 값의 규모가 1e-9 이하라면 이는 지나치게 큰 값입니다.

0이 아닌 기본값은 사용자의 테스트가 완전히 부적절하게 통과되는 결과를 초래할 수 있습니다. 반면 기본값을 사용하여 0을 대상으로 한 테스트가 처음에 실패하면, 사용자는 테스트를 통과시키기 위해 해당 문제에 적합한 값을 선택하라는 안내를 받게 됩니다.

참고: 이 PEP의 작성자는 기본 절대 허용 오차를 제공하는 numpy allclose()함수를 사용하는 자신의 여러 테스트를 다시 검토하여 기본값이 적절한지 확인하기로 했습니다.

사용자가 rel_tol 매개변수를 0.0으로 설정하면 절대 허용 오차만 결과에 영향을 줍니다. 함수의 목표는 아니지만, 이를 순수한 절대 허용 오차 검사로 사용할 수도 있습니다.

구현

Python의 샘플 구현은 GitHub에서 확인할 수 있습니다(2015년 1월 22일 기준).

https://github.com/PythonCHB/close_pep/blob/master/is_close.py

이 구현에는 사용자가 적용할 상대 허용 오차 테스트를 선택할 수 있게 하는 플래그가 있습니다. 이 PEP에서는 해당 플래그를 유지하자는 것이 아니라 약한 테스트를 선택할 것을 제안합니다.

이곳에는 이 PEP의 초안과 테스트 코드 등도 있습니다.

https://github.com/PythonCHB/close_pep

상대 차이

두 수가 서로 얼마나 가까운지 생각하는 방법은 본질적으로 두 가지가 있습니다.

절대 차이: 단순히 abs(a-b)입니다.

상대 차이: abs(a-b)/scale_factor [2]입니다.

절대 차이는 충분히 단순하므로, 이 제안에서는 상대 차이에 초점을 맞춥니다.

일반적으로 스케일 인자는 고려 중인 값의 함수이며, 예를 들면 다음과 같습니다.

  1. 입력값 중 하나의 절댓값
  2. 두 값의 절댓값 중 최댓값
  3. 두 값의 절댓값 중 최솟값
  4. 두 값의 산술 평균의 절댓값

이에 따라 두 값 a와 b가 서로 가까운지 판별하는 다음과 같은 가능성이 도출됩니다.

  1. abs(a-b) <= tol*abs(a)
  2. abs(a-b) <= tol * max( abs(a), abs(b) )
  3. abs(a-b) <= tol * min( abs(a), abs(b) )
  4. abs(a-b) <= tol * abs(a + b)/2

참고: (2)와 (3)은 다음과 같이 작성할 수도 있습니다.

  1. (abs(a-b) <= abs(tol*a)) or (abs(a-b) <= abs(tol*b))
  2. (abs(a-b) <= abs(tol*a)) and (abs(a-b) <= abs(tol*b))

(Boost에서는 이를 “weak” 및 “strong” 정식화 [3]라고 부릅니다.) 이는 계산 측면에서 아주 조금 더 효율적이므로 예제 코드에서 사용됩니다.

이러한 각 정식화는 약간씩 다른 결과를 낳을 수 있습니다. 그러나 허용 오차 값이 작다면 차이도 상당히 작습니다. 실제로 사용 가능한 부동 소수점 정밀도보다 작은 경우가 많습니다.

차이가 얼마나 발생합니까?

근접성을 판단할 방법을 선택할 때는 한 테스트를 사용할지 다른 테스트를 사용할지에 따라 차이가 얼마나 발생할 수 있는지, 즉 한 테스트는 통과하지만 다른 테스트는 통과하지 못하는 값이 몇 개나 있는지(또는 값의 범위가 어떻게 되는지) 알고 싶을 수 있습니다.

가장 큰 차이는 허용 가능한 절대 차이를 값 중 큰 값 또는 작은 값으로 조정하는 옵션 (2)와 (3) 사이에 있습니다.

delta를 큰 값으로 정의한 허용 가능한 절대 허용 오차와 작은 값으로 정의한 허용 가능한 절대 허용 오차의 차이로 정의합니다. 즉, 두 테스트에서 서로 다른 결과를 얻으려면 두 입력 값이 달라야 하는 정도입니다. tol은 상대 허용 오차 값입니다.

분석을 조금 더 쉽게 하기 위해 a가 더 큰 값이고 ab가 모두 양수라고 가정합니다. 따라서 delta는:

delta = tol * (a-b)

또는:

delta / tol = (a-b)

테스트를 통과하는 가장 큰 절대 차이인 (a-b)는 허용 오차와 더 큰 값을 곱한 값과 같습니다.:

(a-b) = tol * a

delta 식에 대입하면:

delta / tol = tol * a

따라서:

delta = tol**2 * a

예를 들어 a = 10, b = 9, tol = 0.1 (10%)인 경우에는 다음과 같습니다.

최대 허용 오차 tol * a == 0.1 * 10 == 1.0

최소 허용 오차 tol * b == 0.1 * 9.0 == 0.9

delta = (1.0 - 0.9) = 0.1 또는 tol**2 * a = 0.1**2 * 10 = .1

이 경우 최대 허용 오차 테스트와 최소 허용 오차 테스트 사이의 절대 차이는 상당할 수 있습니다. 그러나 제안된 함수의 주된 사용 사례는 계산 결과를 테스트하는 것입니다. 이 경우에는 훨씬 더 작은 크기의 상대 허용 오차가 선택될 가능성이 높습니다.

예를 들어 1e-8의 상대 허용 오차는 파이썬 부동 소수점에서 사용할 수 있는 정밀도의 약 절반입니다. 이 경우 두 테스트 간의 차이는 1e-8**2 * a 또는 1e-16 * a이며, 이는 파이썬 부동 소수점의 정밀도 한계에 가깝습니다. 상대 허용 오차를 제안된 기본값인 1e-9(또는 그보다 작은 값)로 설정하면 두 테스트 간의 차이는 부동 소수점 정밀도의 한계에 묻히게 됩니다. 즉, 네 가지 방법 각각이 a와 b의 모든 값에 대해 정확히 동일한 결과를 냅니다.

또한 일반적으로 허용 오차는 유효 숫자 1자리로 정의됩니다. 즉, 1e-9는 약 9자리의 소수 정확도를 지정합니다. 따라서 가능한 여러 테스트 간의 차이는 허용 오차가 지정된 정밀도보다 훨씬 낮습니다.

대칭성

상대 비교는 대칭적일 수도 있고 비대칭적일 수도 있습니다. 대칭 알고리즘의 경우에는 다음과 같습니다.

isclose(a,b)는 항상 isclose(b,a)와 같습니다.

상대 근접성 테스트가 값 중 하나만 사용하는 경우(위의 (1)과 같은 경우), 결과는 비대칭적입니다. 즉, isclose(a,b)가 isclose(b,a)와 반드시 같지는 않습니다.

가장 적절한 접근 방식은 어떤 질문을 하는지에 따라 달라집니다. 질문이 “이 두 숫자가 서로 가까운가?”라면 명확한 순서가 없으므로 대칭 테스트가 가장 적절합니다.

그러나 질문이 “계산된 값이 이 알려진 값의 x% 이내인가?”라면 허용 오차를 알려진 값에 맞춰 조정하는 것이 적절하므로 비대칭 테스트가 가장 적절합니다.

이전 섹션에서 일반적인 사용 사례에서는 어느 접근 방식을 사용하든 동일하거나 유사한 결과를 얻는다는 점이 분명합니다. 이러한 경우 이 제안의 목표는 놀라운 결과를 생성할 가능성이 가장 낮은 함수를 제공하는 것입니다.

대칭 접근 방식은 매력적인 일관성을 제공합니다. 즉, 동등성의 대칭성을 반영하며 사람들을 혼란스럽게 할 가능성이 낮습니다. 대칭 테스트는 인자를 설정할 순서에 대해 사용자가 고민할 필요도 덜어 줍니다. 또한 평가 순서가 명확하게 정의되지 않을 수 있는 경우가 있을 수 있다는 지적도 있었습니다. 예를 들어 값 집합의 모든 값을 서로 비교하는 경우가 그렇습니다.

사용자가 어떤 값이 알려진 값의 특정 범위 이내에 있는지 알아야 하는 경우도 있을 수 있습니다. 이러한 경우에는 테스트를 직접 작성하기만 하면 충분합니다.:

if a-b <= tol*a:

(이 경우 a > b라고 가정합니다.) 이 특정 경우를 위한 함수를 제공할 필요성은 거의 없습니다.

이 제안에서는 대칭 테스트를 사용합니다.

어떤 대칭 테스트입니까?

고려되는 대칭 테스트는 세 가지입니다.

두 값의 산술 평균을 사용하는 경우, 먼저 두 값을 더한 후 2로 나누어야 하며, 이로 인해 매우 큰 숫자에서 inf로의 추가 오버플로가 발생할 수 있습니다. 또는 각 값을 2로 나눈 후 더해야 하며, 이로 인해 매우 작은 숫자에서 0으로의 언더플로가 발생할 수 있습니다. 이러한 현상은 float 값의 극한에서만 발생하지만, 기능 범위를 줄이거나 계산 순서를 결정하기 위해 값을 확인하는 복잡성을 추가할 만큼 이 방법에 이점이 없다고 판단했습니다.

따라서 boost “weak” 테스트 (2), 즉 더 큰 값을 사용하여 허용 오차를 조정하는 방법과, 더 작은 값을 사용하여 허용 오차를 조정하는 Boost “strong” (3) 테스트가 남습니다. 허용 오차가 작을 때는 동일한 결과를 내지만, 이 제안에서는 boost “weak” 테스트 사례를 사용합니다. 이 방식은 대칭적이며 매우 큰 허용 오차에서 더 유용한 결과를 제공합니다.

큰 허용 오차

가장 일반적인 사용 사례에서는 기본값 1e-9 정도의 작은 허용 오차가 사용될 것으로 예상됩니다. 그러나 사용자가 상당히 다른 두 값이 서로 특정 범위 이내에 있는지 알고자 하는 사용 사례도 있을 수 있습니다. “a가 b의 200% (rel_tol = 2.0) 이내인가? 이 경우 두 값 중 하나가 0이면 strong 테스트는 두 값이 서로 해당 범위 이내에 있다고 표시하지 않습니다. 그러나 weak 방식은 더 큰 값(0이 아닌 값)을 테스트에 사용하므로, 한 값이 0이면 true를 반환합니다. 예를 들어 0은 10의 200% 이내입니까? 10의 200%는 20이므로 10의 200% 이내 범위는 -10에서 +30까지입니다. 0은 해당 범위에 포함되므로 True를 반환합니다.

기본값

상대 허용 오차와 절대 허용 오차에는 기본값이 필요합니다.

상대 허용 오차 기본값

두 값이 “close”한 것으로 간주되기 위해 필요한 상대 허용 오차는 전적으로 사용 사례에 따라 달라집니다. 그럼에도 상대 허용 오차는 1e-16(파이썬 float의 대략적인 정밀도)보다 커야 합니다. 1e-9라는 값은 가능한 여러 방법이 동일한 결과를 내는 가장 큰 상대 허용 오차이며, 파이썬 float에서 사용할 수 있는 정밀도의 약 절반이기도 하므로 선택되었습니다. 일반적인 경우, 우수한 수치 알고리즘이 사용 가능한 정확도 자릿수의 절반보다 많이 잃을 것으로 예상되지는 않으며, 훨씬 더 큰 허용 오차가 허용된다면 사용자는 그 경우에 적절한 값을 고려해야 합니다. 따라서 1e-9는 많은 경우에 “그냥 작동할” 것으로 예상됩니다.

절대 허용 오차 기본값

절대 허용 오차 값은 주로 0과 비교하는 데 사용됩니다. 값이 0에 “close”한지를 판단하는 데 필요한 절대 허용 오차는 전적으로 사용 사례에 따라 달라집니다. 또한 유용한 범위에는 사실상 한계가 없으며, 예상되는 값은 파이썬 float의 범위 안 어디에나 있을 수 있습니다. 따라서 기본값으로 0.0이 선택되었습니다.

특정 사용 사례에서 사용자가 0과 비교해야 하는 경우, 테스트는 처음에는 반드시 실패하며 사용자는 적절한 값을 선택할 수 있습니다.

실제로 0과 비교하는 것이 일반적인 사용 사례라는 의견이 제시되었습니다(증거에 따르면 numpy 함수는 0과 함께 자주 사용됩니다). 이 경우 “유용한” 기본값을 두는 것이 바람직합니다. 값이 1 정도인 경우 부동 소수점 정밀도의 약 절반에 해당하는 1e-8 정도의 값이 제안되었습니다.

그러나 Zen의 말을 인용하면 다음과 같습니다. “모호한 상황에서는 추측하려는 유혹을 거부하십시오.” 사용자가 대부분 1.0에 가까운 값에 관심을 가질 것이라고 추측하면 더 작은 값과 함께 사용할 때 근거 없이 통과하는 테스트가 발생하며, 이는 사용자가 적절한 값을 신중하게 선택하도록 요구하는 것보다 잠재적으로 더 해롭습니다.

예상되는 사용 사례

가장 주요하게 예상되는 사용 사례는 다양한 형태의 테스트입니다. 즉, “결과가 제가 예상한 결과에 가깝게 계산되었습니까?”와 같은 테스트입니다. 이러한 테스트는 공식 단위 테스트 모음의 일부일 수도 있고 아닐 수도 있습니다. 이러한 테스트는 명령줄에서 일회성으로, IPython 노트북에서, 독스트링 테스트의 일부로, 또는 if __name__ == "__main__" 블록에서 간단한 assert로 사용할 수 있습니다.

또한 암시적 함수의 간단한 반복 해법에 대한 종료 기준으로 사용하기에도 적절한 함수입니다.:

guess = something
while True:
    new_guess = implicit_function(guess, *args)
    if isclose(new_guess, guess):
        break
    guess = new_guess

부적절한 사용 사례

부동 소수점 비교의 한 가지 사용 사례는 수치 알고리즘의 정확도를 테스트하는 것입니다. 그러나 이 경우 수치 분석가는 이상적으로 신중한 오차 전파 분석을 수행하고 무엇을 테스트해야 하는지 정확히 이해해야 합니다. 또한 ULP(마지막 위치의 단위) 비교가 필요할 가능성도 있습니다. 이 함수가 그러한 상황에서 유용할 수는 있지만, 신중한 고려 없이 그런 방식으로 사용하도록 의도된 것은 아닙니다.

기타 접근법

unittest.TestCase.assertAlmostEqual

(https://docs.python.org/3/library/unittest.html#unittest.TestCase.assertAlmostEqual)

차이를 계산하고, 지정된 소수점 이하 자릿수(기본값 7)로 반올림한 다음 0과 비교하여 값이 근사적으로(또는 근사적으로 동일하지 않게) 같은지 테스트합니다.

이 메서드는 순수한 절대 허용 오차 테스트이며 상대 허용 오차 테스트의 필요성은 다루지 않습니다.

numpy isclose()

http://docs.scipy.org/doc/numpy-dev/reference/generated/numpy.isclose.html

numpy 패키지는 이 제안과 유사한 사용 사례를 위해 벡터화된 함수 isclose()와 allclose()를 제공합니다:

isclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False)

두 배열이 허용 오차 내에서 원소별로 같은지 여부를 나타내는 불리언 배열을 반환합니다.

허용 오차 값은 양수이며, 일반적으로 매우 작은 수입니다. 상대 차이(rtol * abs(b))와 절대 차이 atol을 더하여 a와 b 사이의 절대 차이와 비교합니다

이 접근 방식에서는 본 제안에서 사용하는 or 방식 대신, 절대 허용 오차와 상대 허용 오차를 더합니다. 이는 계산상 더 단순하며, 상대 허용 오차가 절대 허용 오차보다 큰 경우 덧셈은 아무 영향을 미치지 않습니다. 하지만 절대 허용 오차와 상대 허용 오차의 크기가 비슷한 경우, 허용되는 차이는 예상보다 약 두 배 커지게 됩니다.

이는 함수를 이해하기 어렵게 만들며, 이 맥락에서는 계산상의 이점도 없습니다.

더 결정적으로, 전달된 값이 절대 허용 오차에 비해 작은 경우, 상대 허용 오차는 예상치 못하게 완전히 묻혀버릴 수 있습니다.

이러한 이유로, 본 제안에서는 절대 허용 오차의 기본값이 0이며 — 사용자가 해당 값들에 적합한 값을 직접 선택해야 합니다.

Boost 부동소수점 비교

Boost 프로젝트( [3] )는 부동소수점 비교 함수를 제공합니다. 이는 대칭적인 접근 방식으로, “약한”(두 상대 오차 중 더 큰 값) 옵션과 “강한”(두 상대 오차 중 더 작은 값) 옵션을 모두 제공합니다. 본 제안은 Boost의 “약한” 방식을 사용합니다. 대부분의 경우 결과가 비슷할 것이고 사용자가 어떤 방식을 선택해야 할지 알기 어려울 것이므로, 서로 다른 방식을 선택할 수 있는 옵션을 제공하여 API를 복잡하게 만들 필요는 없습니다.

대안 제안

레시피

주된 대안 제안은 표준 라이브러리 함수를 아예 제공하지 않고, 대신 사용자가 참고할 수 있는 레시피를 제공하는 것이었습니다. 이렇게 하면 레시피가 다양한 옵션을 제공하고 설명함으로써, 사용자가 가장 적합한 것을 선택할 수 있다는 장점이 있습니다. 하지만 이 경우, 그러한 테스트가 필요한 사람은 최소한 해당 함수를 자신의 코드베이스에 복사하고, 사용할 비교 방식을 선택해야 할 것입니다.

zero_tol

한 가지 가능성은 절대 허용 오차 매개변수 대신 영점 허용 오차 매개변수를 제공하는 것이었습니다. 이는 두 인자 중 하나가 정확히 0인 경우에만 적용되는 절대 허용 오차가 됩니다. 이렇게 하면 0이 아닌 모든 값에 대해 완전한 상대 허용 오차 동작을 유지하면서도, 0에 대한 테스트가 동작하도록 할 수 있다는 장점이 있습니다. 하지만 이는 작은 값이 0에는 “가깝다”고 판정되면서도 그보다 더 작은 값에는 “가깝지” 않다는, 잠재적으로 의외의 결과를 초래하기도 합니다. 예를 들어, 1e-10은 0에는 “가깝지”만, 1e-11에는 “가깝지” 않습니다.

절대 허용 오차 없음

0과의 비교에 관한 이러한 문제를 감안할 때, 또 다른 가능성은 상대 허용 오차만 제공하고 0과의 비교는 실패하도록 두는 것이었습니다. 이 경우, 0과의 비교가 관련된 상황에서 사용자는 간단한 절대값 테스트인 abs(val) < zero_tol을 직접 수행해야 할 것입니다.

하지만 이렇게 하면 루프나 컴프리헨션과 같이 여러 값에 대해 동일한 호출을 사용할 수 없게 됩니다. 이는 함수를 훨씬 덜 유용하게 만듭니다. 기본값을 재정의하지 않는 경우, 기본값 abs_tol=0.0이 동일한 효과를 낸다는 점에 유의해야 합니다.

그 밖의 테스트

그 밖에 고려된 테스트들은 모두 위의 상대 오차 절에서 다뤘습니다.

참고 문헌