Bringing the rung together
Over the last four guides we built up two completely separate measuring sticks. One belongs to the problem: conditioning asks how much the true answer moves when the input is nudged, and the condition number kappa puts a number on that sensitivity — well- or ill-conditioned is a property of the question, not of your code. The other belongs to the algorithm: stability asks how faithfully your particular sequence of floating-point steps tracks the exact computation, and backward stability is the gold standard — it means your computed answer is the exact answer to a slightly perturbed input.
The reason we kept these two ideas apart is that they finally lock together into one statement. Conditioning measures how the problem amplifies any perturbation. A backward-stable algorithm guarantees that the perturbation it introduces is tiny. Put them in series and you get the rule this whole rung was climbing toward — the one short inequality that predicts how many digits you will actually keep.
The master rule
Here it is, the sentence to carry out of this rung: the relative forward error of a computed answer is at most the condition number times the relative backward error. The forward error is what you care about — how wrong the answer is. The backward error is what a good algorithm controls — how far the input would have to move to make your answer exactly right. The condition number is the exchange rate between the two. This is the accuracy = conditioning × stability principle in one line.
forward error <= condition number x backward error
(answer wrong) kappa (the PROBLEM) (algorithm slip)
relative ~ machine epsilon
forward error <= kappa x (if BACKWARD STABLE)
~ 1e-16 (double)
example: kappa ~ 1e8 , backward error ~ 1e-16
=> forward error <= 1e8 x 1e-16 = 1e-8
=> keep ~8 of your ~16 digits ; the other ~8 are goneNow watch the magic of plugging in a backward-stable algorithm. Its backward error is held down to about machine epsilon — roughly 1e-16 in double precision. So the inequality collapses to: relative forward error is at most kappa times 1e-16. The algorithm has done absolutely everything it could; what is left is pure conditioning. This is exactly the rule-of-thumb error bound you met earlier, and it is why a condition number near 1e8 silently eats about 8 of your ~16 significant digits before you even start interpreting the result.
Four cases, two knobs
Because accuracy is a product of two factors, there are exactly four corners to live in, and naming the corner you are in is half of debugging. Think of conditioning and stability as two independent knobs; the answer is good only when both are turned the right way.
- Well-conditioned problem + stable algorithm: the happy case. kappa is small and backward error is near epsilon, so the forward error is near epsilon too. You get the digits you paid for.
- Well-conditioned problem + unstable algorithm: your own fault, and fixable. The problem was fine, but a careless step (think catastrophic cancellation) injected a large backward error. Rewrite the formula or swap the algorithm and the accuracy comes back.
- Ill-conditioned problem + stable algorithm: the honest loss. The code is blameless, backward error is near epsilon, yet kappa is huge — so the forward error is large anyway. No software trick rescues you; only changing the problem (reformulate, regularize, add precision) helps.
- Ill-conditioned problem + unstable algorithm: the worst of both, and the easiest to misdiagnose — you cannot tell from the wrong answer alone whether the problem or the code is at fault until you separate the two knobs.
Why a perfect algorithm still fails
Case 3 deserves to be sat with, because it overturns a comforting intuition. You might assume that if your code is bug-free and numerically careful — fully backward stable — then your answers must be accurate. The master rule says no. Stability bounds only the backward error; the forward error is that bound multiplied by kappa. When kappa is enormous, even a flawless algorithm hands back garbage in the leading digits, and it is genuinely the right answer to a question one rounding-error away from the one you asked.
A concrete picture: solving A x = b where A is badly ill-conditioned, say a Vandermonde or Hilbert-like matrix with a large matrix condition number. Run a textbook stable solver and the residual ||A x_computed - b|| comes out tiny — the algorithm is innocent — yet x_computed can differ from the true x in its very first digit. The map from b to x stretches errors by kappa(A), and no choice of solver can un-stretch them. By the way, this is partly why you rarely form A inverse to solve A x = b: explicitly inverting an ill-conditioned matrix amplifies the damage rather than avoiding it.
Living with the rule
Because you only ever get to control one of the two factors, your strategy splits along the same seam. You make the algorithm better by choosing a backward-stable method and avoiding moves that destroy numerical stability — but this can only push the backward error down toward epsilon; it can never beat the condition number. To go further you must change the problem: reformulate it, regularize it, rescale the variables, or fall back to higher precision so that epsilon itself shrinks and buys back some of the lost digits.
And keep the honest framing of the whole subject in view. Every numerical answer is an approximation; floating-point arithmetic is not exact real arithmetic — 0.1 has no exact binary form and addition is not even associative. The accuracy = conditioning × stability rule is the lens that tells you, for any given computation, how much of that unavoidable approximation will survive to the end. It does not promise you a good answer. It promises you an honest accounting of where the error came from — and that is what lets you act instead of guess.