수치 해석(numerical analysis)에서, 치명적 취소(catastrophic cancellation)는 두 개의 가까운 숫자에 대한 좋은 근사를 빼면 원래 숫자의 차이에 대해 매우 나쁜 근사를 산출할 수 있는 현상입니다.[1][2]
예를 들어, 두 개의 기둥이 있으며, 하나가 길이이고 다른 하나가 길이이고, 그것들이 센티미터까지만 적합한 자로 측정되면, 근사는 와 가 될 수 있습니다. 이것들은 실제 길이에 대한, 상대 오차(relative error)에서, 좋은 근사일 수 있습니다: 근사는 오차에서 실제 길이의 2% 미만, 입니다.
어쨌든, 만약 근사적인 길이는 빼면, 그 차이는 일 것이지만, 심지어 길이 사이의 실제 차이는 입니다. 근사의 차이 는 실제 값의 차이 크기 의 100%만큼 오차입니다.
치명적 취소는 입력의 크기에 영향을 받지 않습니다—그것은 크고 작은 입력에 똑같이 적용됩니다. 그것은 차이의 크기와 입력 오차에 따라 달라집니다. 와 에 대한 근사로 에서 를 빼거나, 와 에 대한 근사로 에서 를 빼면 정확하게 같은 오차가 발생합니다.
위의 예제에서와 같이, 차이가 정확하게 계산되더라도 치명적 취소가 발생할 수 있습니다—이는 부동-점 산술(floating-point arithmetic)과 같은 특정 종류의 산술 속성이 아닙니다; 오히려, 그것은 입력이 자체로 근사일 때 뺄셈에 내재되어 있습니다. 실제로, 부동-점 산술에서, 입력이 충분히 가까울 때, 부동-점 차이는 스테벤츠 보조정리(Sterbenz lemma)에 의해 정확하게 계산됩니다—부동-점 뺄셈 연산에 의해 도입되는 반올림 오차는 없습니다.
Formal analysis
형식적으로, 치명적 취소는 뺄셈이 입력 근처에서 나쁜-조건되기 때문에 발생합니다: 심지어 근사 와 가 각각 참 값 와 로부터 작은 상대 오차(relative errors)와 를 가지더라도, 참 값의 차이 로부터 근사의 차이 의 상대 오차는 참 값의 차이에 반비례합니다:
따라서, 참 값의 차이 로부터 근사의 정확한 차이 의 상대 오차는 다음과 같습니다:
이는 참 값 와 가 가까우면 임의적으로 커질 수 있습니다.
In numerical algorithms
부동-점 산술에서 가까운 숫자를 빼는 것이 항상 치명적 취소 또는 어떤 오류를 유발하는 것은 아닙니다—스테벤츠 보조정리(Sterbenz lemma)에 의해, 만약 숫자가 충분히 가깝다면, 부동-점 차이는 정확합니다. 그러나 취소는 다른 부동-점 산술에서 반올림으로 인해 발생한 입력에서 오차를 증폭시킬 수 있습니다.
Example: Difference of squares
숫자 와 가 주어지면, 부동-점 산술 에 의해 수학 함수 를 계산하려는 순진한 시도는 와 가 크기에서 가까울 때 치명적인 취소의 대상이 되는데, 왜냐하면 뺄셈은 제곱에서 반올림 오류를 노출할 수 있기 때문입니다. 부동-점 산술 에 의해 평가되는 대안적인 인수화 는 치명적 취소를 방지하는데, 왜냐하면 그것은 뺄셈에서 이어지는 반올림 오차 도입을 방지하기 때문입니다.[2]
예를 들어, 이고 이면, 차이 의 참 값은 입니다. IEEE 754 binary64 산술에서, 대안적인 인수화 를 평가하는 것은 (반올림 없이) 정확한 결과를 제공하지만, 순진한 표현 을 평가하는 것은 부동-점 숫자 를 제공하며, 그 중 절반 미만의 자릿수가 정확하고 나머지 (밑줄이 그어진) 자릿수는 중간 제곱 값을 계산할 때 반올림으로 인해 손실된 누락된 항 을 반영합니다.
어쨌든, 에 대해 를 가정합니다. 그런-다음 이고 입니다; 그것들 사이의 차이를 라고 부르며, 이 숫자는 거의 0에 가까운 매우 작은 차이입니다. 만약 가 임의의 오차 를 갖는 다음을 제공하는 부동-점 산술에서 평가되면,
여기서 는 부동-점 반올림을 나타내며, 둘 다 에 매우 가까운, 서로 가까운 두 개의 숫자의 다음 차이를 계산하는 것은
하나의 입력에서 오류 를 의 계수로 증폭할 수 있습니다—이는 가 거의 0이기 때문에 매우 큰 인수입니다. 예를 들어, 이면, 의 실제 값은 근사적으로 이지만, IEEE 754 binary64 산술에서 순진한 로그 공식을 사용하면 를 제공하며, 16 자릿수 중 5 자릿수만 정확하고 남은 부분 (밑줄 그어진)은 모든 쓰레기입니다.
에 대해 의 경우에서, 항등식 을 사용하는 것은 취소를 방지하는데 왜냐하면 이지만 이므로, 뺄셈은 뺄셈은 취소되지 않는 같은 부호로 사실상 덧셈입니다.
Example: Radix conversion
소프트웨어 프로그램의 숫자 상수는 종종 C 조각 double x = 1.000000000000001과 같이 십진수로 작성됩니다; x라는 IEEE 754 binary64 변수를 선언하고 초기화하는 것입니다. 어쨌든, 은 binary64 부동-점 숫자가 아닙니다; 이 조각에서 x가 초기화될 가장 가까운 값은 입니다. 비록 10진수 부동-점에서 2진수 부동-점으로의 기수 변환은 작은 상대 오류만 발생하지만, 치명적 취소로 인해 훨씬 더 큰 오류로 증폭될 수 있습니다:
doublex=1.000000000000001;// rounded to 1 + 5*2^{-52}doubley=1.000000000000002;// rounded to 1 + 9*2^{-52}doublez=y-x;// difference is exactly 4*2^{-52}
차이 는 입니다. 에서 x와 에서 y의 상대 오차는 둘 다 미만이고, 부동-점 뺄셈 y - x은 스테벤츠 보조정리에 의해 정확하게 계산됩니다.
그러나 비록 입력이 좋은 근사치이고, 뺄셈이 정확하게 계산되더라도, 근사의 차이 은 십진수로 쓰일 때 원래 값의 차이 에서 이상의 상대 오차를 가집니다: 치명적 취소는 기수 변환에서 작은 오차를 출력에서 큰 오차로 증폭시켰습니다.
Benign cancellation
취소는 때때로 수치 알고리듬에서 유용하고 바람직합니다. 예를 들어, 2Sum 및 Fast2Sum 알고리듬은 모두 부동-점 숫자 자체로서 부동-점 덧셈 연산에서 오차가 무엇인지 정확하게 계산하기 위해 반올림 오차 후 그러한 취소에 의존합니다.
함수 는, 점 에서 순진하게 평가되면, 를 반올림할 때 의 자릿수 대부분을 잃게 됩니다. 어쨌든, 함수 자체는 0에 가까운 입력에서 바른-조건(well-conditioned)됩니다. 그것을 다음과 같이 다시 작성하면,에서 취소를 이용하여 직접 평가되는 에서 오차를 방지합니다.[2] 이것은 분자 에서 취소와 분모 에서 취소가 서로 상쇄되기 때문에 작동합니다; 함수 는 가 에 대한 좋은 근사를 제공하고 따라서 가 에 대한 좋은 근사를 제공하는 영 근처에서 충분히-바르게 조건됩니다.