A discrepancy can originate in the mathematical problem, the selected algorithm, or its implementation. This tutorial uses controlled examples to separate problem sensitivity from algorithmic error and to show why residual and forward error answer different questions.
Its exact solution is \((1,1)\). The code uses 80-digit decimal arithmetic so that the observed amplification is not an accidental binary64 effect. The maximum norm is used for both input and output changes.
The separated system amplifies this direction by about 3. The nearly dependent system amplifies it by about \(2\times10^{12}\): a relative input change near \(5\times10^{-17}\) produces a relative output change of \(10^{-4}\). This is problem sensitivity observed in high precision.
Exercise: vary the separation
Change exercise_delta and predict the amplification before running the cell. Try powers of ten between 1 and \(10^{-12}\). Which quantity in the equations suggests the trend?
The exact solution change contains the ratio \(\eta/\delta\). The sweep below checks how that factor appears in the relative amplification. One direction is being sampled; this is not a complete worst-case condition-number calculation.
For a unique nonzero exact solution \(x\), a common relative normwise choice is \(\rho_X=\|\hat{x}-x\|_X/\|x\|_X\). With multiple solutions, \(S(d)\) must represent the acceptable solutions or the intended branch. If \(x\) is replaced by a justified numerical reference, the measured value is an estimate of the unknown exact forward error.
The backward error instead measures distance in the data space:
This definition asks for the infimum of the sizes of admissible input changes that make the computed result exact. It is incomplete unless the allowed changes, preserved structure, norm, and scaling in \(\rho_D\) are stated. For \(Ax=b\) with \(A\) fixed and \(r=b-A\hat{x}\), choosing \(\rho_D=\|\Delta b\|/\|b\|\) gives \(\eta_b=\|r\|/\|b\|\), because \(\hat{x}\) exactly solves \(A\hat{x}=b-r\).
Hold the problem fixed and change the algorithm
Now consider the dimensionless polynomial
\[
p(x)=x^2-10^8x+1.
\]
The direct formula subtracts the square root from \(10^8\) to obtain the small root. The reformulation computes the large root using addition, then uses the fact that the product of the roots is one. Both solve the same mathematical problem in the same binary64 format.
The high-precision reference is recomputed with 80 and 100 decimal digits. Their relative difference checks that reference precision is far beyond what this comparison needs.
The direct calculation has roughly 25% forward error and requires a large coefficient perturbation under the stated backward measure. The reformulated calculation has forward and backward errors near binary64 rounding scale. This is evidence about the algorithms because the polynomial, input coefficients, arithmetic format, reference, and metrics are held fixed.
Compare residual with forward error
Return to the nearly dependent system with \(\delta=10^{-12}\). Its exact solution is \((1,1)\). The candidate \((0,2)\) is visibly far away, but calculate its residual and the right-hand-side perturbation that would make it exact.
The relative backward error is about \(5\times10^{-13}\), but the relative forward error is one. The candidate exactly solves a nearby system, and this ill-conditioned problem amplifies that small input change. A small residual is therefore evidence of a nearby solved problem, not necessarily of proximity to the desired solution.
Evidence record
A diagnosis should record which object was tested, which metric was used, and what remains unproven. This prevents “ill-conditioned” or “unstable” from becoming an unsupported label.
evidence = {"conditioning_experiment": {"arithmetic": "Decimal with 80 digits of precision","norm": "maximum norm on dimensionless quantities","input_perturbation": input_perturbation,"observed_amplification_delta_1": ( conditioning_results["1"]["observed_amplification"] ),"observed_amplification_delta_1e_12": observed_conditioning,"limitation": "One perturbation direction, not a full condition number.", },"algorithm_experiment": {"problem": "Small root of x**2 - 1e8*x + 1","reference_check_relative_difference": reference_difference,"direct_forward_error": quadratic_results["direct"]["forward_error"],"direct_backward_error": quadratic_results["direct"]["backward_error"],"reformulated_forward_error": ( quadratic_results["reformulated"]["forward_error"] ),"reformulated_backward_error": ( quadratic_results["reformulated"]["backward_error"] ),"limitation": "One coefficient set, not a general stability proof.", },"residual_experiment": {"relative_forward_error": relative_forward_error,"relative_rhs_backward_error": relative_rhs_backward_error,"conclusion": ("A small scaled residual does not imply small forward error ""for this ill-conditioned system." ), },}evidence
{'conditioning_experiment': {'arithmetic': 'Decimal with 80 digits of precision',
'norm': 'maximum norm on dimensionless quantities',
'input_perturbation': Decimal('1E-16'),
'observed_amplification_delta_1': Decimal('3.0000000000000000000000000000000000000000000000000000000000000000000000000000000'),
'observed_amplification_delta_1e_12': Decimal('2000000000001.0000000000000000000000000000000000000000000000000000000000000000000'),
'limitation': 'One perturbation direction, not a full condition number.'},
'algorithm_experiment': {'problem': 'Small root of x**2 - 1e8*x + 1',
'reference_check_relative_difference': Decimal('4.1999999999999995799999999999999579999999999999915999999999999978999999999999995E-79'),
'direct_forward_error': Decimal('0.2549419403076172620058059692382887005805969238296151161193847659975290298461915105581283569335266948'),
'direct_backward_error': Decimal('0.1460936722945242059648786141111309714162763770152708971046628882161945422366802853447337934745734873'),
'reformulated_forward_error': Decimal('7.907743916987153941692944892356164065364028626385689635114354499370422999748222689215609611052530019E-17'),
'reformulated_backward_error': Decimal('3.953871958493576336403115389080986758609425472278465196290785691824888572980141881324657977789542996E-17'),
'limitation': 'One coefficient set, not a general stability proof.'},
'residual_experiment': {'relative_forward_error': Decimal('1'),
'relative_rhs_backward_error': Decimal('4.9999999999975000000000012499999999993750000000003124999999998437500000000781250E-13'),
'conclusion': 'A small scaled residual does not imply small forward error for this ill-conditioned system.'}}
Pitfalls and optional extensions
Do not call a problem ill-conditioned because one low-precision algorithm failed; perturb the mathematical inputs independently of that algorithm.
Do not call an algorithm stable because it returned a small residual on one ill-conditioned problem.
Do not treat one observed perturbation direction as the full condition number.
Try smaller and larger \(\delta\) values while ensuring the decimal precision remains sufficient for the selected perturbation.
Change \(B\) in the quadratic and identify where the direct formula’s errors become consequential.
Compare another norm, but state its scaling and explain which scientific quantity it represents.