# 절대 오차와 상대 오차 분석

#### 절대 오차의 정의와 개념

실제 해를 정확히 알고 있다고 가정했을 때, 어떤 수치해석 기법이나 알고리즘을 통해 근사값을 얻었을 때 발생하는 오차를 분석하기 위해 절대 오차와 상대 오차를 정의한다. 실제 값(정확한 해)을 $x$라 하고, 수치적으로 구해진 근사값을 $\tilde{x}$라 하면, 절대 오차는 다음과 같이 정의한다.

$$
|x - \tilde{x}|
$$

이때 $x - \tilde{x}$는 참값과 근사값의 차이를 의미하고, 그 크기가 0에 가까울수록 근사값이 참값에 가까움을 의미한다. 절대 오차는 말 그대로 “절대적인 편차”를 측정하기 때문에, 값의 스케일이 클 때나 작을 때나 변별력이 떨어질 수 있다. 예를 들어 참값이 매우 큰 경우에는 절대 오차가 작아 보여도 상대적으로 오차가 매우 작게 느껴질 수 있고, 반대로 참값이 매우 작은 경우에는 아주 작은 절대 오차라도 상대적으로 큰 오차로 해석될 수도 있다.

절대 오차는 일반적으로 다음과 같은 상황에서 집중적으로 사용한다. 예컨대 측정 장비가 정밀도가 고정되어 있어서 동일한 단위 범위에서 오차를 파악해야 할 때, 혹은 변수가 한정된 스케일 내에서만 움직일 때 등이다. 그러나 수치 계산 과정에서는 단순히 절대 오차만 보는 것보다 상대 오차와 함께 해석하는 경우가 대부분이며, 이는 수치해석에서 수치적 안정성을 점검할 때 중요한 지표가 된다.

#### 상대 오차의 정의와 개념

상대 오차는 측정되거나 계산된 값이 참값에 비해 얼마나 비율적으로 벗어나 있는지를 보여주는 지표다. 참값을 $x$라 하고, 수치적으로 구한 근사값을 $\tilde{x}$라 할 때, 상대 오차는

$$
\frac{|x - \tilde{x}|}{|x|}
$$

로 정의된다. 값의 스케일에 관계없이 전체적인 비율로 오차 크기를 파악할 수 있으므로, 서로 다른 단위나 범위를 갖는 값들을 비교하거나, 참값의 크기가 매우 크거나 매우 작을 때 오차를 평가하는 데 효과적이다.

상대 오차는 분모에 참값이 들어가므로, $x = 0$에 가까운 값들에서는 정의가 모호해질 수 있다. 예를 들어 실제 해가 0인 경우에는 나눗셈이 불가능하기 때문에 상대 오차를 정의할 수 없다. 또한 실제 해가 0에 아주 가까우면 작은 차이도 큰 상대 오차로 확대 해석될 수 있다는 점에 유의해야 한다. 이처럼 상대 오차는 값의 크기가 크게 변하는 상황에서 매우 유용하지만, 0에 가까운 해에 대해서는 다른 관점이나 정규화 기법을 동반하여 해석해야 한다.

#### 절대 오차와 상대 오차의 비교

절대 오차는 오차가 발생한 “양”을 직접 측정하고, 상대 오차는 “비율”의 관점에서 측정한다. 어떤 수치 계산 결과를 해석할 때, 절대 오차와 상대 오차를 모두 확인해야 하는 중요한 이유는 다음과 같은 배경이 있다. 수치 해석에서는 주어진 문제의 스케일(scale)이 매우 중요하며, 미소한 값이 오차에 민감하거나 매우 큰 값이 상대적으로 낮은 오차를 나타낼 때 적절한 관점이 필요하기 때문이다.

특히 컴퓨터를 이용한 부동소수점 계산에서, 참값이 매우 크거나 매우 작으면 내부 표현의 한계로 인해 연산 오류가 누적될 수 있다. 이러한 상황에서 절대 오차가 작다고 해서 좋은 근사라고 단정 지을 수 없고, 상대 오차 역시 절대 오차와 함께 해석해야 더 정확한 판단을 내릴 수 있다.

#### 절대 및 상대 오차와 부동소수점 연산의 관계

컴퓨터 내부에서 모든 실수 연산은 근사적으로 이루어지며, 부동소수점 표준(예: IEEE 754)에 의해 정밀도가 제한된다. 예를 들어 $x$와 $\tilde{x}$의 차이가 매우 작을 때, 두 값이 같은 부동소수점 표현을 공유한다면 $x-\tilde{x}=0$이 아닌 데도 연산결과 0으로 처리될 수 있다. 이처럼 하드웨어 자체에서 발생하는 양자화(quantization) 현상은 필연적으로 절대 오차와 상대 오차에 영향을 미친다.

예시로 $x$가 매우 큰 값이고 $\tilde{x}$가 부동소수점 한계에 의해 비슷한 범위를 갖는 어떤 수로 저장될 때, 실제로는 작은 차이가 존재하더라도 컴퓨터가 표현할 수 없으므로 $x = \tilde{x}$로 판단하는 경우가 빈번하다. 즉, 소수점 이하 정밀도가 제한되어 있기 때문에, $|x - \tilde{x}|$의 최솟값이 특정 범위 이하로는 구분되지 못하는 상황이 벌어진다.

상대 오차 관점에서는 스케일이 큰 값들에 대해 작은 차이가 미미하게 해석될 수 있어서 수치적 계산이 안정적으로 보일 수도 있으나, 반대로 $x$가 0에 가깝다면 아주 작은 차이도 상대 오차가 크게 나타날 수 있다. 결국 다양한 맥락에서 절대 오차와 상대 오차를 종합적으로 고려해야 한다는 결론이 자연스럽게 도출되며, 특히 알고리즘을 구현할 때는 모수의 크기가 극단적이지 않은지, 부동소수점 환경에서 잘 처리될 수 있는지를 점검해야 한다.

#### 간단한 계산 예시 (Octave)

다음 예시는 Octave에서 절대 오차와 상대 오차를 단순 비교하는 코드다. 수치적으로 해석할 때 주의해야 할 점을 보여주기 위해 매우 큰 값과 매우 작은 값을 예제로 보여준다.

```octave
x_large = 1.0e15;      % 실제 값이 매우 큰 경우
x_small = 1.0e-15;     % 실제 값이 매우 작은 경우

% 실제 해 x_large, 근사값 x_large_approx
x_large_approx = x_large + 1.0e10;  % 실제 해보다 조금 큰 값을 근사치로 설정
abs_error_large = abs(x_large - x_large_approx);
rel_error_large = abs(x_large - x_large_approx) / abs(x_large);

% 실제 해 x_small, 근사값 x_small_approx
x_small_approx = x_small + 1.0e-19; % 실제 해보다 약간 큰 값을 근사치로 설정
abs_error_small = abs(x_small - x_small_approx);
rel_error_small = abs(x_small - x_small_approx) / abs(x_small);

disp(['abs_error_large = ', num2str(abs_error_large)]);
disp(['rel_error_large = ', num2str(rel_error_large)]);
disp(['abs_error_small = ', num2str(abs_error_small)]);
disp(['rel_error_small = ', num2str(rel_error_small)]);
```

위 코드를 통해 매우 큰 수의 경우에는 절대 오차가 커도 상대 오차는 작게 나타날 수 있음을, 반대로 매우 작은 수에서는 절대 오차가 아주 작음에도 상대 오차가 크게 나타날 수 있음을 확인할 수 있다. 이처럼 어떤 문제를 다룰 때는 문제의 특성과 목표가 무엇인지, 그리고 대상 값의 스케일이 어떤 범위에 분포하는지를 고려해야 한다.

#### 유효숫자(Significant Figures)와 오차

절대 오차와 상대 오차는 정확도(accuracy)의 개념을 수치적으로 표현하기 위한 것이지만, 유효숫자(significant figures) 역시 흔히 사용되는 기법이다. 유효숫자란 숫자를 표기했을 때 “의미 있게 믿을 수 있는 자릿수”를 말한다. 예를 들어 어떤 근사값 $\tilde{x}$가 실제 해 $x$와 비교했을 때 소수점 아래 특정 자리까지 일치한다면, 그만큼 “유효한 숫자”를 가진다고 해석한다.

일반적으로 유효숫자 자릿수($n$개)를 확보했다는 것은 다음 불등식을 만족한다는 의미다.

$$
\frac{|x - \tilde{x}|}{|x|} \le 5 \times 10^{-n}
$$

이 식은 상대 오차를 기준으로 유효숫자를 파악하는 전형적인 방식이다. 즉, $x$와 $\tilde{x}$의 상대적 차이가 $5 \times 10^{-n}$ 이하라면, 두 값은 최소한 $n$자리의 유효숫자를 확보하고 있다고 본다. 여기서 5라는 계수는 반올림 기준에서 나온 것이다. 유효숫자 개수를 통해 값의 “정밀도”와 “확실하게 믿을 수 있는 범위”를 파악할 수 있다.

실제로 수치해석 과정에서 유효숫자와 절대·상대 오차를 동시에 고려하는 이유는, 부동소수점 연산이 반올림을 유발하기 때문이다. 예컨대 double precision(배정도)에서는 보통 15\~16자리 정도의 유효숫자를 표현할 수 있다. 그러나 여러 번의 사칙연산을 거치면서 오차가 조금씩 누적되면, 결과의 실제 유효숫자는 그보다 훨씬 줄어들 수도 있다.

#### 오차 전파(Error Propagation)

하나의 계산 과정에서 발생한 작은 오차가 이후 연산을 거치며 어떻게 퍼지고 커지는지 살피는 일은 수치해석에서 중요한 주제다. 보통 덧셈, 뺄셈, 곱셈, 나눗셈으로 구성된 복합 연산이 진행될 때, 각 단계에서 발생하는 오차(절대·상대)가 최종 결과에 어떤 영향을 미치는지 분석할 필요가 있다.

**덧셈과 뺄셈에서의 오차 전파**

덧셈(또는 뺄셈) 연산으로 $x + y$를 계산한다고 가정하자. $x$와 $y$ 각각에 오차가 포함되어 있을 수 있다. 두 값의 근사값을 각각 $\tilde{x}$, $\tilde{y}$라고 했을 때, 실제로 머신이 수행하는 연산은 $\tilde{x} + \tilde{y}$가 된다. 이때 실제 해는 $x + y$이며, $x + y$와 $\tilde{x} + \tilde{y}$의 차이가 최종 오차가 된다.

덧셈이나 뺄셈의 경우, 특히 큰 수와 작은 수를 동시에 다룰 때 상대 오차가 크게 변할 수 있다. 예를 들어,

$$
x \approx 10^{10}, \quad y \approx 1
$$

인 경우, $x + y = 10^{10} + 1$이지만, 부동소수점 정밀도가 충분하지 않다면 $10^{10}$과 1의 차이를 표현하지 못하고 $10^{10}$으로만 저장될 수 있다. 그렇게 되면 실제로는 절대 오차가 $1$이지만, 상대 오차로 따지면 $\frac{1}{10^{10}} = 10^{-10}$로 꽤 작아 보인다. 반면 $x$가 아주 작은 값이라면 전혀 다른 해석이 나오므로 주의해야 한다.

**곱셈과 나눗셈에서의 오차 전파**

곱셈과 나눗셈은 덧셈·뺄셈과는 다른 양상으로 오차가 전개된다. 예를 들어 두 근사값 $\tilde{x}$와 $\tilde{y}$에 대한 곱셈 결과는 이론적인 값 $xy$와는 달리 부동소수점 반올림을 통해 오차가 누적될 수 있다. 특히 지수부(exponent)가 매우 큰 값들끼리 곱하거나, 매우 작은 값들끼리 곱하면 반올림으로 인해 의미 있는 자릿수가 크게 줄어드는 사례가 발생한다.

나눗셈도 마찬가지다. 예를 들어 매우 작은 값으로 나누게 될 때, 분모가 0에 가깝다면 상대 오차가 폭발적으로 커질 수 있고, 0에 정확히 근접한 값을 분모로 잡는 것만으로도 알고리즘이 수치적으로 불안정해질 수 있다. 이처럼 곱셈과 나눗셈에 수반되는 오차 전파는 때때로 덧셈·뺄셈보다 더 큰 위험 요인이 될 수 있으므로, 알고리즘을 설계할 때는 연산 순서와 형태를 잘 구성하는 것이 중요하다.

#### 합성함수의 오차 전파

여러 연산이 합성된 함수를 $f(x)$라 하고, 알고리즘상 입력값이 $x$가 아니라 근사값 $\tilde{x}$로 주어졌을 때, 결과값은 $f(\tilde{x})$가 된다. 이때 $f(x)$와 $f(\tilde{x})$의 차이가 최종 오차다. 수치해석 전반에서 “오차 전파”를 분석한다는 것은, $|x - \tilde{x}|$(또는 이 둘의 상대 오차)가 함수 $f$를 거쳐 나왔을 때 $|f(x) - f(\tilde{x})|$가 얼마나 커지는지를 예측하고 제어하는 행위를 의미한다.

함수 $f$가 선형이라면, 오차의 전파가 단순한 형태를 띠나, 실제로는 비선형(Nonlinear)인 경우가 많다. 따라서 미분을 통한 해석(예: 민감도 분석, 조건수(condition number) 등)을 활용하여, 입력값의 작은 변화가 결과에 큰 차이를 초래하는지를 점검해야 한다. 조건수가 큰 문제는 입력에 발생하는 작은 오차도 결과를 크게 뒤흔들기 때문에, 절대 오차와 상대 오차가 문제가 되는 상황이 자주 생긴다.

#### 머신 엡실론(Machine Epsilon)과 최소 오차 분해능

수치해석에서 중요한 상수로 머신 엡실론(machine epsilon)이 있다. 이는 부동소수점 형식에서 1과 구분되는 가장 작은 양의 수를 의미하며, 반올림 오차의 한계를 규정한다. IEEE 754 표준에서 double precision인 경우 대략 $2.220446049250313 \times 10^{-16}$ 정도가 머신 엡실론에 해당한다.

머신 엡실론은 “연산 중 발생할 수 있는 최소 오차 단위”로 여겨진다. 예를 들어 실질적으로 절대 오차가 머신 엡실론 미만으로 줄어드는 것은 불가능에 가깝다고 볼 수도 있다. 또한 1보다 훨씬 큰 값이나 1보다 훨씬 작은 값에 대해서도, 각각 그 스케일에 맞춰 1의 위치가 변하기 때문에 “상대적” 엡실론이 달라진다. 이때 발생하는 현상으로는 denormalized(서브노멀) 영역이 존재하는데, 이 영역에서는 수들이 정상정규화(normalized) 형태가 아닌 특수한 방법으로 표현되어 극도로 작은 수를 허용한다. 그러나 그만큼 정밀도 손실이 커지고, 오차가 누적될 위험이 높아진다.

#### 수치적 안정성(Numerical Stability)과 오차의 이해

수치 알고리즘이 “안정적(stable)”이라고 말하기 위해서는 입력값이나 중간 연산에서 발생하는 작은 오차가 최종 결과를 심하게 왜곡시키지 않아야 한다. 다시 말해, 알고리즘이 수행되는 동안 절대 오차와 상대 오차가 적절히 억제되어야 한다. 예를 들어 어떤 알고리즘이 “수치적으로 불안정(unstable)”하다면, 아무리 이론적으로는 정확도가 뛰어난 기법이라도 컴퓨터에서 실제로 돌렸을 때는 심각한 오차가 발생할 수 있다.

이러한 안정성 판단에서, 절대 오차와 상대 오차는 주요 지표가 된다. 알고리즘의 출력이 참값 대비 얼마나 차이가 있는지(정확도), 그리고 과정에서 오차가 얼마나 급격히 증폭되는지(안정성)를 함께 고려해야 한다. 실제로 안정성을 논할 때는 조건수, 잔차(residual), backward error 같은 개념도 동원하여 더 포괄적으로 분석하지만, 그 바탕에는 항상 “얼마만큼의 오차가 발생하고 이를 어떻게 볼 것인가”라는 절대·상대 오차 분석이 깔려 있다.

#### 전진 오차와 후진 오차 (Forward Error & Backward Error)

수치해석에서 “오차”를 다루는 방식은 참값 $x$와 근사값 $\tilde{x}$의 단순 비교를 넘어, 알고리즘이 실제 문제를 얼마나 잘 반영하는가 하는 관점으로도 확장된다. 대표적으로 전진 오차(forward error)와 후진 오차(backward error)는 수치 알고리즘의 성능을 다각도로 살펴볼 수 있게 해 주는 개념이다.

**전진 오차 (Forward Error)**

전진 오차는 “수치해석에서 구한 해 $\tilde{x}$가 실제 해 $x$와 얼마나 멀리 떨어져 있는가?”를 나타내는 것으로, 지금까지 논의된 절대 오차 혹은 상대 오차가 전진 오차의 전형적 예다. 예컨대 문제 $f(x) = 0$에서 해를 $x^*$라 하고, 알고리즘으로 얻은 해를 $\tilde{x}^*$라 하면

$$
\text{Forward Error} = |\tilde{x}^\* - x^\*|
$$

혹은 상대화하여

$$
\text{Relative Forward Error} = \frac{|\tilde{x}^\* - x^*|}{|x^*|}
$$

와 같이 정의할 수 있다. 전진 오차는 문제의 “입력”과 “출력” 간 직접적인 차이를 측정하므로, 매우 직관적이고 즉각적으로 해석할 수 있다는 장점이 있다. 그러나 알고리즘이 어떤 식으로 문제를 변형하여 계산하는지, 그 과정에서 실제 문제를 얼마나 충실히 구현하는지는 전진 오차만으로는 충분히 설명하기 어렵다.

**후진 오차 (Backward Error)**

후진 오차는 “수치 알고리즘이 실제 문제를 (약간 변경된) 어떤 다른 문제로 해석하고 답을 구했다고 볼 때, 그 변경 정도가 얼마나 작은가?”를 측정한다. 즉, 알고리즘의 결과 $\tilde{x}^\*$가 정확한 해가 되도록 만드는 “가상의 문제”가 실제 문제로부터 얼마나 멀리 떨어져 있는지 본다.

예를 들어 $\mathbf{A}\mathbf{x} = \mathbf{b}$ 문제에서, 실제 해는 $\mathbf{x}^*$이고 수치 알고리즘 결과는 $\tilde{\mathbf{x}}^*$라 하자. 이때 후진 오차 분석은 “$\mathbf{A}\mathbf{x} = \mathbf{b}$가 아니라 $\mathbf{A} + \Delta \mathbf{A}, \mathbf{b} + \Delta \mathbf{b}$ 같은 조금 다른 문제에 대하여 $\tilde{\mathbf{x}}^\*$가 정확한 해가 된다면, $\Delta \mathbf{A}$와 $\Delta \mathbf{b}$가 얼마나 작아야 하는가?”를 묻는다. 이 관점으로 접근하면 다음을 정의할 수 있다.

$$
(\mathbf{A} + \Delta \mathbf{A}) , \tilde{\mathbf{x}}^\* = \mathbf{b} + \Delta \mathbf{b}
$$

이때 $|\Delta \mathbf{A}|$와 $|\Delta \mathbf{b}|$가 매우 작다면, 우리는 “알고리즘이 실제 문제를 크게 왜곡하지 않고 풀었다.”라고 평가할 수 있다. 즉, 실제 문제와 아주 근접한(작게 변형된) 문제의 해를 구한 셈이다. 이처럼 후진 오차가 작다는 것은 알고리즘이 “수치적으로 안정적”일 가능성을 시사한다.

두 종류의 오차는 서로 다른 측면을 강조한다. 전진 오차는 “실제 해와의 직접적 차이”를 보며, 후진 오차는 “문제 정의의 왜곡 정도”를 본다. 수치적으로 안정적(stable)인 알고리즘이라면, 후진 오차가 작아서 실제 문제를 크게 훼손하지 않은 채로 근사 해를 구한다고 볼 수 있다. 반대로 전진 오차가 아무리 작아 보여도, 후진 오차가 매우 크다면 “알고리즘이 완전히 다른 문제를 풀었는데 그게 우연히 실제 해와 비슷해진” 상황일 수도 있다.

#### 조건수 (Condition Number)

어떤 문제를 풀 때, 입력값의 작은 변화가 출력값에 얼마나 큰 영향을 미치는지 정량적으로 측정하기 위해 조건수(condition number) 개념이 자주 활용된다. 가장 흔히 인용되는 예시는 선형시스템 $\mathbf{A}\mathbf{x}=\mathbf{b}$에서의 조건수 $\kappa(\mathbf{A})$이다. 적절한 행렬 노름 $|\cdot|$에 대해

$$
\kappa(\mathbf{A}) = |\mathbf{A}| \cdot |\mathbf{A}^{-1}|
$$

로 정의한다. 조건수가 크다는 것은 “$\mathbf{A}\mathbf{x}=\mathbf{b}$ 문제에서 $\mathbf{b}$나 $\mathbf{A}$에 발생하는 작은 교란(perturbation)이 해 $\mathbf{x}$에 크게 증폭될 수 있다.”는 의미다. 다시 말해, 전진 오차와 후진 오차가 괴리되는 문제가 생길 수 있으며, 수치적으로 민감(sensitive)한 문제가 된다.

조건수가 작은 문제가 이상적으로 안정적이고, 조건수가 큰 문제는 불안정하게 해석될 가능성이 높다. 하지만 정확히 말하면, 조건수 자체는 문제의 “내재적 특성”일 뿐 알고리즘의 성능을 결정짓지는 않는다. 조건수가 나쁜(큰) 문제를 다룰 때도 알고리즘이 후진 오차 관점에서 좋은 성능을 보일 수는 있다. 단지 문제 자체가 민감하기 때문에, 그 결과가 조금만 달라도 전진 오차가 크게 발생할 위험이 있음을 유의해야 한다.

#### 전진·후진 오차와 조건수의 연관성

후진 오차가 작더라도, 조건수가 매우 큰 문제라면 전진 오차가 크게 발생할 수 있다. 이를 간단한 공식으로 나타내면

$$
\frac{|\mathbf{x}^\* - \tilde{\mathbf{x}}^*|}{|\mathbf{x}^*|}  \quad \le \quad  \kappa(\mathbf{A}) \cdot \frac{|,\Delta \mathbf{b}|!/!|\mathbf{b}|}{|\mathbf{x}^\*|}
$$

와 같은 형태로, 문제의 조건수 $\kappa(\mathbf{A})$가 전진 오차를 한 번 더 크게 증폭시키는 역할을 한다. (여기서는 단순화된 표현이지만, 실제 분석에서는 $\mathbf{A}$와 $\mathbf{b}$ 모두에 생기는 교란을 종합적으로 계산해야 한다.) 결국 조건수가 크면, 작아 보이는 후진 오차도 전진 오차로 해석했을 때는 눈덩이처럼 불어날 수 있다는 점이 중요하다.

아래 다이어그램은 수치해석 전반의 오차 발생 과정을 간단히 표현한다. 전진 오차와 후진 오차가 서로 다른 단계에서 어떻게 해석되는지 시각화하여, 오차 개념이 어떤 단계에서 정의되는지를 한눈에 확인할 수 있다.

{% @mermaid/diagram content="flowchart TB
A\[Exact Problem] --> B\[Mathematical Model]
B --> C\[Implementation in Code]
C --> D\[Run on Computer / Rounding]
D --> E\[Result]

```
subgraph Error Classification
   F1(Forward Error):::box --> F2(Backward Error):::box
end

style F1 fill:#E0E0E0,stroke:#333,stroke-width:1px
style F2 fill:#E0E0E0,stroke:#333,stroke-width:1px" %}
```

#### 오차 개념의 종합적 활용

* 전진 오차는 우리가 “직접적으로 구하고자 하는 양”과 “실제 양”의 차이를 가늠하는 데 필수적이다.
* 후진 오차는 “실제로 풀린 문제”가 얼마나 원래 문제에 가까운지를 측정하고, 알고리즘의 안정성을 진단하는 중요한 근거가 된다.
* 조건수는 문제 자체의 “민감도(sensitivity)”를 보여주어, 작은 교란이 결과에 미치는 영향을 정량적으로 나타낸다. 조건수가 클수록 결과가 왜곡될 위험이 커지고, 상대·절대 오차 해석이 까다로워진다.

이처럼 절대 오차와 상대 오차를 비롯한 여러 오차 개념은 문제 특성(조건수)과 알고리즘 특성(전진·후진 오차)을 입체적으로 파악하기 위해 함께 활용되어야 한다. 실제로는 더 정교한 이론(Backward Error Analysis, Residual 분석 등)을 통해 문제 설정, 알고리즘 설계, 구현 과정에서의 수치적 특성을 전방위로 살피는 작업이 중요하다.

#### 오차 허용 기준(Tolerance)과 반복법(Iterative Methods)

수치해석에서 절대 오차와 상대 오차는 단지 결과 해의 정확도를 평가하는 데에만 쓰이지 않고, 반복법으로 문제를 풀 때 수렴 여부를 판정하는 기준으로도 활용된다. 반복 알고리즘(예: 고정점 반복법, Newton-Raphson, Gauss-Seidel 등)은 초기값에서 출발하여 점진적으로 해를 근사해 가는데, 매 반복 단계마다 얻어지는 근사값 사이의 차이가 충분히 작아지면 알고리즘을 중단한다. 이때 “충분히 작다”를 구체화하기 위해 절대 오차 기준 혹은 상대 오차 기준을 설정하게 된다.

예를 들어 어떤 반복법에서 $k$번째 근사값을 $x\_k$, $(k+1)$번째 근사값을 $x\_{k+1}$라고 하면, 다음과 같은 중단 조건을 고려할 수 있다.

절대 오차 기준.

$$
|,x\_{k+1} - x\_k,| \le \varepsilon\_\text{abs}
$$

상대 오차 기준.

$$
\frac{|,x\_{k+1} - x\_k,|}{|,x\_{k+1},|} \le \varepsilon\_\text{rel}
$$

여기서 $\varepsilon\_\text{abs}$는 절대 오차 허용치(absolute tolerance), $\varepsilon\_\text{rel}$는 상대 오차 허용치(relative tolerance)다. 어떤 경우에는 두 조건을 동시에 사용하여,

$$
|,x\_{k+1} - x\_k,| \le \varepsilon\_\text{abs}  \quad \text{또는} \quad \frac{|,x\_{k+1} - x\_k,|}{|,x\_{k+1},|} \le \varepsilon\_\text{rel}
$$

이 만족될 때 반복을 멈출 수도 있다. 특히 $x\_{k+1}$이 0에 근접하는 해여서 분모가 지나치게 작아지는 경우를 대비하거나, $x\_{k+1}$이 매우 큰 값일 때 상대 오차가 쉽게 작아지는 일을 고려하기 위해, 서로 다른 기준을 중첩하여 쓰는 것이 일반적이다.

#### 절대 오차와 상대 오차의 혼합 기준

수치해석 솔버나 라이브러리(예: MATLAB, NumPy, Eigen 등)에서는 절대 오차와 상대 오차를 함께 고려해 종료 조건을 설정하는 것이 보편적이다. 예컨대 어떤 라이브러리에서는 다음과 비슷한 형태로 반복을 멈춘다.

$$
|,x\_{k+1} - x\_k,| \le \max\bigl(\varepsilon\_\text{abs}, ,\varepsilon\_\text{rel}\cdot|,x\_{k+1},|\bigr)
$$

이런 형태는 $x\_{k+1}$의 크기에 따라 적절히 절대 오차와 상대 오차 중 엄격한 쪽을 적용하는 방식으로, $x\_{k+1}$이 아주 큰 값이든, 매우 작은 값이든, 0 근처든, 한쪽에 치우치지 않고 어느 정도의 안정성을 확보한다.

절대 오차와 상대 오차를 혼합하여 설정하는 이유는, 실전 문제에서 해의 스케일을 미리 정확히 예측하기가 어려운 경우가 많기 때문이다. 특정 문제에서는 해가 $10^5$ 정도가 될 수도 있고, 다른 문제에서는 $10^{-10}$ 정도의 해를 다룰 수도 있다. 단일 기준을 사용하면 한쪽 극단에서 과도한 반복이나 과소평가된 수렴 문제가 발생하므로, 혼합 기준이 안전장치 역할을 한다.

#### 잔차(Residual) 기반의 오차 평가

$x$가 어떤 방정식의 해라고 할 때, 직접 $|,x - \tilde{x},|$를 계산하기 어려운 경우가 있다. 방정식이 복잡하거나 참값을 알 수 없을 때는, 실제로 문제에 대입했을 때의 “잔차(residual)”를 보고 오차를 추정하기도 한다. 예를 들어 비선형 방정식 $f(x)=0$에서, 근사 해 $\tilde{x}$가 주어지면 잔차는 $|f(\tilde{x})|$로 정의한다.

잔차가 0에 가까워진다면, $f(\tilde{x}) \approx 0$이므로 “참 해에 가까워지고 있겠다”는 직관이 가능하다. 물론 $|f(\tilde{x})|$가 극도로 작더라도, $f$가 매우 급격히 변하는 구간이라면 실제 해와 크게 차이날 수도 있으므로 주의가 필요하다. 이러한 이유로, 잔차 기반의 해석에서 추가로 절대 오차 혹은 상대 오차 추정치를 함께 살펴보는 것이 이상적이다.

#### 예제 코드 (Python)

다음은 Python을 사용하여 간단한 비선형 방정식 $f(x)=\cos x - x$의 해를 Newton-Raphson 방법으로 찾으면서, 절대 오차와 잔차를 동시에 모니터링하는 예시다. 상대 오차를 포함한 정교한 기준을 설정해도 무방하다.

```python
import math

def f(x):
    return math.cos(x) - x

def fprime(x):
    return -math.sin(x) - 1

x0 = 1.0         # 초기값
tol_abs = 1e-8   # 절대 오차 기준
max_iter = 50
for k in range(max_iter):
    x1 = x0 - f(x0)/fprime(x0)
    abs_error = abs(x1 - x0)
    residual = abs(f(x1))
    print(f"Iter={k}, x={x1:.12f}, abs_err={abs_error:e}, residual={residual:e}")
    if abs_error < tol_abs:
        break
    x0 = x1
```

이 예시에서 $|,x\_{k+1} - x\_k,|$가 충분히 작아지면 반복을 중단한다. 출력 로그를 보면, 각 단계에서 $x$의 업데이트 폭(절대 오차)와 잔차가 점차 줄어드는 것을 확인할 수 있다. 상대 오차 기준이 필요한 경우, 예컨대

```python
rel_error = abs(x1 - x0) / max(abs(x1), 1.0)
```

등으로 정의하여 함께 체크할 수도 있다. 수치해석 문제 해결 시에는 어떤 기준을 얼마만큼 엄격히 둘 것인지가 문제의 특성, 해의 크기, 계산 비용 등에 따라 달라진다.

#### 축적오차(Accumulated Error)와 반올림(Rounding Error)

수치연산을 많이 수행하는 경우, 각 단계에서 발생하는 반올림 오차가 축적(accumulate)될 수 있다. 반복법에서는 수십\~수백 번 이상의 연산이 이뤄지며, 특히 곱셈·나눗셈 등을 빈번히 사용할 때 부동소수점 정밀도가 제한되는 환경에서는 정밀도 손실이 누적될 가능성이 있다.

축적오차가 심각해지면, 실제로는 충분히 수렴해야 할 알고리즘이 수렴하지 못하거나, 전혀 엉뚱한 해로 치우칠 수 있다. 이때 절대 오차와 상대 오차가 이상치(Outlier)로 튀어나오거나, 잔차가 갑작스레 커지는 현상 등이 관찰될 수 있다. 그러므로 오차가 얼마나 누적될 수 있는지, 어느 연산에서 특히 심각한 반올림이 발생할 수 있는지 예측하고 대비하는 것이 중요하다.

축적오차를 완화하기 위해서는 연산 순서를 재조정하거나(큰 수와 작은 수의 연산 순서를 바꾼다든지), 고정소수점 대신 배정도(double precision)로 계산한다든지, 심지어 여러 배정도를 지원하는 사중정밀(quad precision)을 사용하기도 한다. 문제의 특성과 구현 환경에 따라 이런 전략을 미리 구상해두는 것이 수치적 안정성을 확보하는 핵심이다.

#### 유효숫자 손실(Loss of Significance)과 치명적 상쇄(Catastrophic Cancellation)

컴퓨터에서 수치 계산을 수행할 때, “유효숫자 손실” 혹은 “유효자릿수 손실”이라는 문제가 발생할 수 있다. 특히 큰 수에서 작은 수를 빼거나, 거의 같은 두 수를 뺄 때 유효숫자가 극단적으로 줄어드는 현상을 “치명적 상쇄(catastrophic cancellation)”라고 부른다. 이때 절대 오차 혹은 상대 오차의 관점에서 상당히 불리한 상황이 발생할 수 있으며, 결과적으로 신뢰할 수 없는 해를 얻게 되는 심각한 문제가 생길 수 있다.

예를 들어 부동소수점 계산에서 다음처럼 매우 큰 수에 근접한 값을 두 개 가지고 있다고 하자.

$$
a = 1.0000000 \times 10^{6}, \quad b = 0.9999999 \times 10^{6}.
$$

이 값들을 실제로는

$$
a = 1{,}000{,}000, \quad b = 999{,}999.9
$$

정도로 볼 수 있지만, 컴퓨터 부동소수점에선 유효숫자 제한 때문에 둘의 차이를 정확히 계산하기 어렵다. $a - b$는 이론적으로 $0.1$이어야 하지만, 내부 표현에서 반올림이 일어나면 $0.1000000$ 대신 다른 값으로 치우치거나(예: $0.0999999$), 더 극단적인 경우 $0.0$이 될 수도 있다. 이렇게 서로 비슷한 수를 뺄 때 유효숫자가 급감하여, 절대·상대 오차가 폭발적으로 커지는 문제가 바로 치명적 상쇄다.

이 문제는 특히 함수 계산에서 “차분 연산”을 사용할 때 자주 발생한다. 예컨대 수치미분을 위해 작은 $h$에 대해

$$
f'(x) \approx \frac{f(x+h) - f(x)}{h}
$$

을 계산할 때, $f(x+h)$와 $f(x)$가 매우 근접하면 분자 부분이 부동소수점 반올림으로 인해 부정확하게 계산된다. 이렇게 발생한 오차가 곱셈이나 나눗셈을 통해 증폭되면, 절대 오차와 상대 오차 모두 큰 타격을 입을 수 있다.

#### 치명적 상쇄의 예시 (Python)

다음 예시는 $a \approx b$인 두 수를 만들어 뺄셈 연산을 해보면서, 치명적 상쇄가 어떤 식으로 나타나는지 살펴보는 간단한 데모다.

```python
import math

a = 1.0000000e6
b = 0.9999999e6

true_diff = 0.1   # 이론상 a - b = 1000000 - 999999.9

diff_computed = a - b
abs_err = abs(diff_computed - true_diff)
rel_err = abs_err / abs(true_diff)

print(f"a           = {a}")
print(f"b           = {b}")
print(f"true_diff   = {true_diff}")
print(f"diff_computed = {diff_computed}")
print(f"absolute error = {abs_err}")
print(f"relative error = {rel_err}")
```

실행 결과에서 $a-b$가 $0.1$과 큰 차이를 보이지 않는다면, 이 예시에서는 아직 유효숫자가 충분했을 가능성이 있다. 하지만 $a$와 $b$의 크기를 더 키우거나, 두 값이 서로 훨씬 더 비슷하게 만들면, 컴퓨터가 내부에서 정밀도를 유지하기 어려워 작은 차이가 0으로 처리되거나 다른 오차를 발생시킬 수 있다. 그 결과 절대 오차가 $10^{-7}$ 수준이거나, 심지어 0.1이 완전히 사라져 0이 될 수도 있다. 그렇게 되면 상대 오차가 무한대로 커지거나 계산 불가능한 값이 되기도 한다.

#### 유효숫자 손실 완화 기법

치명적 상쇄를 피하기 위해서는 대체 공식을 사용하거나, 연산 순서를 재배치하여 수의 스케일 차이가 지나치게 큰 상황을 만들지 않도록 주의해야 한다. 예를 들어, 근사적으로 근접한 두 수의 차이를 직접 구하는 대신에, 항등식이나 부드러운 근사식을 활용하는 방법을 쓸 수 있다.

잘 알려진 예시로 삼각함수 $1 - \cos(x)$는 $x^2$ 근방에서 매우 작은 값을 갖는다. 이를 부정확하게 계산하지 않으려면,

$$
1 - \cos(x) = 2 \sin^2!\Bigl(\frac{x}{2}\Bigr)
$$

공식을 이용하면, $x$가 매우 작은 값이라도 $\sin^2(\frac{x}{2})$ 쪽을 통해 좀 더 안전하게 연산을 수행할 수 있다. 비슷하게, 수치 해석 과정에서 근접한 두 식의 차를 직접 계산해야 할 경우, 수치적으로 안전한 대안식을 마련해두면 치명적 상쇄 위험을 줄일 수 있다.

#### 고정소수점 vs. 배정도 vs. 다중 정밀도

컴퓨터의 수치 표현 형식에 따라 유효숫자 손실이 발생하는 정도도 달라진다. 보통 single precision(단정도)보다는 double precision(배정도)이, double precision보다는 quadruple precision(사중정밀)이 훨씬 많은 유효 자릿수를 제공한다. 필요한 경우에는 ‘다중 정밀도(multi-precision) 라이브러리’를 도입하여 연산 정밀도를 사용자가 직접 높일 수도 있다. 그러나 정밀도를 높이는 데 따른 계산 비용의 증가 역시 무시할 수 없으므로, 문제가 요구하는 수준의 정확도, 반복 횟수, 허용 시간 등을 종합적으로 고려해야 한다.

#### 수치적 문제 해결에서의 종합 전략

결국 수치계산 전반에서 절대 오차와 상대 오차의 개념을 단순 오차 측정 지표에만 그치지 않고, 연산 순서 및 형식을 재설계하는 “수치 안정화” 과정에 적극 활용해야 한다. 큰 값과 작은 값이 섞여 있는 경우, 근접한 값들의 차를 직접 구해야 하는 경우, 비선형 함수의 변동 폭이 급격한 경우 등 다양한 상황에서 유효숫자 손실이 언제 어떤 식으로 벌어지는지 살피면서, 치명적 상쇄가 발생하지 않도록 지속적으로 관리·개선할 필요가 있다.
