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]를 비롯한 Python 이외의 여러 시스템에서도 이러한 검사를 제공합니다.

이러한 기존 구현들은 이 기능이 흔히 필요하면서도 직접 작성하기가 간단하지 않다는 것을 보여 주므로, 이 기능은 표준 라이브러리에 포함할 후보가 됩니다.

제안하는 구현

참고: 이 PEP는 python-ideas 메일링 리스트에서 오랫동안 논의한 결과입니다 [1].

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

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

a와 b: 상대적 근접성을 검사할 두 값입니다.

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라는 이름은 기존의 isnan 및 isinf와 일관성을 맞추기 위해 선택되었습니다.

유한하지 않은 수의 처리

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

float가 아닌 타입

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

코드는 최소한 다음 타입의 일부 값을 수용하도록 테스트됩니다:

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

참고: decimal 타입과 올바르고 완전하게 동작하는 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으로 작성한 샘플 구현이 (2015년 1월 22일 기준) GitHub에 공개되어 있습니다:

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가 더 큰 값이고 a와 b가 모두 양수라고 가정합니다. 따라서 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은 Python float에서 사용할 수 있는 정밀도의 약 절반에 해당합니다. 이 경우 두 검사 간의 차이는 1e-8**2 * a, 즉 1e-16 * a이며, 이는 Python float의 정밀도 한계에 가깝습니다. 상대 허용 오차를 제안된 기본값인 1e-9(또는 그보다 작은 값)로 설정하면, 두 테스트 간의 차이는 부동 소수점 정밀도의 한계에 묻혀 사라집니다. 즉, 네 가지 방법 모두 a와 b의 모든 값에 대해 정확히 같은 결과를 냅니다.

또한 일반적인 사용에서 허용 오차는 유효 숫자 1자리로 정의됩니다. 즉, 1e-9는 10진수 약 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의 “약한” 검사 (2)와, 두 값 중 더 작은 값으로 허용 오차를 조정하는 Boost의 “강한” 검사 (3)가 남습니다. 허용 오차가 작으면 두 검사는 같은 결과를 내지만, 이 제안은 boost의 “약한” 검사를 사용합니다. 이 검사는 대칭이며 허용 오차가 매우 클 때 더 유용한 결과를 제공합니다.

큰 허용 오차

가장 흔한 사용 사례는 기본값인 1e-9 정도의 작은 허용 오차일 것으로 예상합니다. 하지만 사용자가 상당히 차이 나는 두 값이 서로 특정 범위 안에 있는지 알고 싶어 하는 사용 사례도 있을 수 있습니다: “a가 b의 200% (rel_tol = 2.0) 이내에 있는가? 이 경우 두 값 중 하나가 0이면 강한 검사는 두 값이 서로 그 범위 안에 있다고 판정하는 일이 결코 없습니다. 반면에 약한 검사는 더 큰 (0이 아닌) 값을 검사에 사용하므로 한 값이 0이면 참을 반환합니다. 예를 들어 0은 10의 200% 이내에 있습니까? 10의 200%는 20이므로 10의 200% 이내 범위는 -10에서 +30까지입니다. 0은 이 범위 안에 있으므로 True를 반환합니다.

기본값

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

상대 허용 오차 기본값

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

절대 허용 오차 기본값

절대 허용 오차 값은 주로 0과 비교할 때 사용됩니다. 어떤 값이 0에 “가까운지” 판단하는 데 필요한 절대 허용 오차는 전적으로 사용 사례에 따라 다릅니다. 또한 유용한 범위에는 사실상 한계가 없습니다 – 기대되는 값은 python float의 한계 내 어디에든 있을 수 있습니다. 따라서 기본값으로 0.0을 선택합니다.

주어진 사용 사례에서 사용자가 0과 비교해야 한다면 테스트는 처음에 반드시 실패할 것이고, 사용자는 그때 적절한 값을 선택할 수 있습니다.

실제로 0과 비교하는 것이 흔한 사용 사례라는 의견이 제시되었습니다(numpy 함수가 0과 함께 자주 사용된다는 증거가 있습니다). 이 경우에는 “유용한” 기본값이 있는 것이 바람직할 것입니다. 1 정도의 값에 대해 부동 소수점 정밀도의 약 절반에 해당하는 1e-8 부근의 값이 제안되었습니다.

그러나 The Zen을 인용하자면 “모호함 앞에서는 추측하려는 유혹을 거부하십시오.” 사용자가 대부분 1.0에 가까운 값을 다룰 것이라고 추측하면, 더 작은 값에 사용했을 때 테스트가 잘못 통과하는 결과를 낳습니다 – 이는 사용자에게 적절한 값을 신중하게 선택하도록 요구하는 것보다 잠재적으로 더 해롭습니다.

예상되는 용도

주로 예상되는 사용 사례는 다양한 형태의 테스트입니다 – “계산된 결과가 예상한 결과에 가깝습니까?” 이러한 테스트는 정식 단위 테스트 스위트의 일부일 수도 있고 아닐 수도 있습니다. 이러한 테스트는 명령줄에서 일회성으로, IPython 노트북에서, doctest의 일부로, 또는 if __name__ == "__main__" 블록 안의 간단한 assert로 사용될 수 있습니다.

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

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

부적절한 용도

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

다른 접근 방식

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

한 가지 가능성은 절대 허용 오차 매개변수 대신 영 허용 오차(zero tolerance) 매개변수를 제공하는 것이었습니다. 이는 인자 중 하나가 정확히 0인 경우에만 적용되는 절대 허용 오차입니다. 이렇게 하면 0이 아닌 모든 값에 대해 상대 허용 오차 동작을 온전히 유지하면서도 0과의 비교 검사가 작동하게 할 수 있다는 장점이 있었을 것입니다. 그러나 이는 작은 값이 0에는 “가깝지만” 그보다 더 작은 값에는 “가깝지 않은”, 잠재적으로 의외의 결과를 낳기도 합니다. 예를 들어, 1e-10은 0에 “가깝지만” 1e-11에는 “가깝지 않습니다”.

절대 허용 오차 없음

0과의 비교에 따르는 문제를 고려할 때, 또 다른 가능성은 상대 허용 오차만 제공하고 0과의 비교는 실패하도록 두는 것이었습니다. 이 경우 비교에 0이 포함되면 사용자는 abs(val) < zero_tol과 같은 간단한 절대 검사를 직접 해야 합니다.

그러나 이렇게 하면 루프나 컴프리헨션에서처럼 일련의 값에 같은 호출을 사용할 수 없습니다. 그러면 함수의 유용성이 훨씬 떨어집니다. 기본값을 재정의하지 않으면 기본값 abs_tol=0.0이 같은 효과를 낸다는 점에 유의하십시오.

기타 검사

검토한 다른 테스트는 모두 위의 상대 오차 절에서 다루었습니다.

참고 문헌