Skip to content

Orthonormal Basis

A basis gives you coordinates. Chapter 2 showed how: to express x\mathbf{x} in a basis B\mathbf{B}, solve Bλ=x\mathbf{B}\boldsymbol{\lambda} = \mathbf{x}. That solve is the price of a general basis, and it is a real price — it costs O(n3)O(n^3), it needs the basis to be well conditioned, and it has to be redone from scratch every time you add a basis vector.

An orthonormal basis removes the solve entirely. Coordinates become inner products, one per basis vector, computed independently. That is the whole point of this page, and it is why every serious numerical routine in the rest of the book — QR, eigendecomposition, SVD, PCA — hands you an orthonormal basis rather than any other kind.

  • Definition 3.9, and the two conditions in it: pairwise orthogonal and unit length.
  • Why BB=I\mathbf{B}^\top\mathbf{B} = \mathbf{I} is the compact form of both conditions at once.
  • Coordinates as inner products, and Parseval’s identity — the squared coordinates add up to the squared length.
  • The Gram-Schmidt construction, and the book’s alternative route through Gaussian elimination on [B~B~B~][\tilde{\mathbf{B}}\tilde{\mathbf{B}}^\top \mid \tilde{\mathbf{B}}].
  • The measured reason nobody implements textbook Gram-Schmidt: at condition number 101010^{10} it loses orthogonality completely, while Householder QR does not budge from machine precision.

Intuition: a coordinate system where the axes do not lean on each other

Section titled “Intuition: a coordinate system where the axes do not lean on each other”

Think about reading coordinates off a graph. If the axes are perpendicular and marked in equal units, reading a point’s xx-coordinate is a single glance: drop a line straight down. Neither axis tells you anything about the other, so the two readings are independent.

Now skew the axes so they meet at 30°30°. Dropping a line “straight down” no longer gives the xx-coordinate, because moving along the second axis also changes your first coordinate. You have to solve for both at once, and the closer the axes get to parallel the more the two readings interfere — which is exactly what an ill-conditioned basis is.

An orthonormal basis is the first picture, in nn dimensions.

diagram Diagram mermaid

The rightmost consequence is the one §3.8 will cash in: the general projection formula B(BB)1B\mathbf{B}(\mathbf{B}^\top\mathbf{B})^{-1}\mathbf{B}^\top collapses to BB\mathbf{B}\mathbf{B}^\top when the basis is orthonormal, because the middle factor becomes the identity.

Equation 3.34 says every basis vector has unit length, since bi=bi,bi=1\lVert\mathbf{b}_i\rVert = \sqrt{\langle\mathbf{b}_i,\mathbf{b}_i\rangle} = 1.

Stack the basis vectors as the columns of B\mathbf{B}. Then the (i,j)(i,j) entry of BB\mathbf{B}^\top\mathbf{B} is exactly bi,bj\langle\mathbf{b}_i, \mathbf{b}_j\rangle, so Equations 3.33 and 3.34 together say

BB=I.\mathbf{B}^\top\mathbf{B} = \mathbf{I} .

That matrix BB\mathbf{B}^\top\mathbf{B} is called the Gram matrix of the basis, and “the basis is orthonormal” and “its Gram matrix is the identity” are the same statement. For a square B\mathbf{B} this also makes it an orthogonal matrix in the sense of Definition 3.8, so B1=B\mathbf{B}^{-1} = \mathbf{B}^\top.

For a general basis, the coordinates λ\boldsymbol{\lambda} of x\mathbf{x} satisfy Bλ=x\mathbf{B}\boldsymbol{\lambda} = \mathbf{x}, so λ=(BB)1Bx\boldsymbol{\lambda} = (\mathbf{B}^\top\mathbf{B})^{-1}\mathbf{B}^\top\mathbf{x}. When the basis is orthonormal the middle factor is I1=I\mathbf{I}^{-1} = \mathbf{I} and this collapses to

λ=Bx,that is,λi=bi,x.\boldsymbol{\lambda} = \mathbf{B}^\top\mathbf{x}, \qquad\text{that is,}\qquad \lambda_i = \langle \mathbf{b}_i, \mathbf{x}\rangle .

Read the second form carefully. Each coordinate is computed from its own basis vector alone. No solve, no interference between coordinates, and — the part that matters for truncation — adding an (n+1)(n{+}1)-th orthonormal direction does not change any of the first nn coordinates. That is why Fourier series, wavelets and PCA all truncate gracefully and a general basis expansion does not.

x2=i=1nλi2when B is orthonormal\lVert \mathbf{x} \rVert^2 = \sum_{i=1}^{n} \lambda_i^2 \qquad\text{when } \mathbf{B} \text{ is orthonormal}

Expand x2=Bλ2=λBBλ=λλ\lVert\mathbf{x}\rVert^2 = \lVert\mathbf{B}\boldsymbol{\lambda}\rVert^2 = \boldsymbol{\lambda}^\top\mathbf{B}^\top\mathbf{B}\boldsymbol{\lambda} = \boldsymbol{\lambda}^\top\boldsymbol{\lambda} and there it is. Under a non-orthonormal basis the middle factor is not the identity and the identity simply fails — measured below, the gap is 5.685.68 on a vector of squared length 5.855.85, which is a 97%97\% error rather than a rounding difference.

The construction is one projection per step, so it belongs to §3.8; the book states it there and this page uses it. Two properties worth naming:

  • The result depends on the order. u1\mathbf{u}_1 is b1\mathbf{b}_1 untouched, so whichever vector you list first survives unchanged. Different orders give different orthonormal bases of the same subspace.
  • The span never changes. Every uk\mathbf{u}_k is bk\mathbf{b}_k minus a combination of earlier vectors, so nothing leaves the subspace and nothing new enters it.

The book also mentions obtaining an ONB by applying Gaussian elimination to the augmented matrix [B~B~B~][\tilde{\mathbf{B}}\tilde{\mathbf{B}}^\top \mid \tilde{\mathbf{B}}], where B~\tilde{\mathbf{B}} has the spanning vectors as columns. It is the same computation with the projections done all at once rather than one at a time, and it inherits the same numerical weakness — forming B~B~\tilde{\mathbf{B}}\tilde{\mathbf{B}}^\top squares the condition number before any elimination happens.

b1=12[11],b2=12[11]\mathbf{b}_1 = \frac{1}{\sqrt{2}}\begin{bmatrix}1\\1\end{bmatrix}, \qquad \mathbf{b}_2 = \frac{1}{\sqrt{2}}\begin{bmatrix}1\\-1\end{bmatrix}
checkworkingresult
b1,b2\langle\mathbf{b}_1,\mathbf{b}_2\rangle12(11+1(1))=12(11)\tfrac{1}{2}(1\cdot1 + 1\cdot(-1)) = \tfrac{1}{2}(1-1)00 — orthogonal
b1,b1\langle\mathbf{b}_1,\mathbf{b}_1\rangle12(1+1)\tfrac{1}{2}(1+1)11 — unit length
b2,b2\langle\mathbf{b}_2,\mathbf{b}_2\rangle12(1+1)\tfrac{1}{2}(1+1)11 — unit length

So BB=I\mathbf{B}^\top\mathbf{B} = \mathbf{I} and this is an ONB. Now use it: take x=(3,1)\mathbf{x} = (3,-1)^\top.

λ1=b1,x=12(31)=22=21.414214\lambda_1 = \langle\mathbf{b}_1,\mathbf{x}\rangle = \tfrac{1}{\sqrt{2}}(3 - 1) = \tfrac{2}{\sqrt{2}} = \sqrt{2} \approx 1.414214 λ2=b2,x=12(3+1)=42=222.828427\lambda_2 = \langle\mathbf{b}_2,\mathbf{x}\rangle = \tfrac{1}{\sqrt{2}}(3 + 1) = \tfrac{4}{\sqrt{2}} = 2\sqrt{2} \approx 2.828427

Two independent inner products, no system solved. Reconstruct to check: λ1b1+λ2b2=22(1,1)+222(1,1)=(1,1)+(2,2)=(3,1)\lambda_1\mathbf{b}_1 + \lambda_2\mathbf{b}_2 = \tfrac{\sqrt{2}}{\sqrt{2}}(1,1) + \tfrac{2\sqrt{2}}{\sqrt{2}}(1,-1) = (1,1) + (2,-2) = (3,-1). ✓

And Parseval: x2=9+1=10\lVert\mathbf{x}\rVert^2 = 9 + 1 = 10, while λ12+λ22=2+8=10\lambda_1^2 + \lambda_2^2 = 2 + 8 = 10. ✓

The book’s Exercise 3.8, worked by Gram-Schmidt

Section titled “The book’s Exercise 3.8, worked by Gram-Schmidt”

Turn b1=(1,1,1)\mathbf{b}_1 = (1,1,1)^\top, b2=(1,2,0)\mathbf{b}_2 = (-1,2,0)^\top into an ONB of the plane they span.

Step 1. u1:=b1=(1,1,1)\mathbf{u}_1 := \mathbf{b}_1 = (1,1,1)^\top.

Step 2. Subtract the projection of b2\mathbf{b}_2 onto u1\mathbf{u}_1:

u1,b2u1,u1=1+2+01+1+1=13\frac{\langle\mathbf{u}_1,\mathbf{b}_2\rangle}{\langle\mathbf{u}_1,\mathbf{u}_1\rangle} = \frac{-1 + 2 + 0}{1+1+1} = \frac{1}{3} u2=b213u1=[120]13[111]=[4/35/31/3]\mathbf{u}_2 = \mathbf{b}_2 - \tfrac{1}{3}\mathbf{u}_1 = \begin{bmatrix}-1\\2\\0\end{bmatrix} - \tfrac{1}{3}\begin{bmatrix}1\\1\\1\end{bmatrix} = \begin{bmatrix}-4/3\\5/3\\-1/3\end{bmatrix}

Confirm orthogonality: u1,u2=43+5313=0\langle\mathbf{u}_1,\mathbf{u}_2\rangle = -\tfrac{4}{3} + \tfrac{5}{3} - \tfrac{1}{3} = 0. ✓

Step 3. Normalise. u1=3\lVert\mathbf{u}_1\rVert = \sqrt{3} and u2=1316+25+1=4232.160247\lVert\mathbf{u}_2\rVert = \tfrac{1}{3}\sqrt{16+25+1} = \tfrac{\sqrt{42}}{3} \approx 2.160247, so

c1=13[111],c2=142[451]\mathbf{c}_1 = \frac{1}{\sqrt{3}}\begin{bmatrix}1\\1\\1\end{bmatrix}, \qquad \mathbf{c}_2 = \frac{1}{\sqrt{42}}\begin{bmatrix}-4\\5\\-1\end{bmatrix}

The 13\tfrac{1}{3} cancels: 142/313(4,5,1)=142(4,5,1)\tfrac{1}{\sqrt{42}/3}\cdot\tfrac{1}{3}(-4,5,-1) = \tfrac{1}{\sqrt{42}}(-4,5,-1).

onb_worked.py
import numpy as np
 
# Example 3.8
b1 = np.array([1.0, 1.0]) / np.sqrt(2)
b2 = np.array([1.0, -1.0]) / np.sqrt(2)
B = np.stack([b1, b2], axis=1)
print("B^T B =\n", np.round(B.T @ B, 15))
 
x = np.array([3.0, -1.0])
lam = B.T @ x                       # coordinates: two inner products, no solve
print("coordinates:", np.round(lam, 6))
print("reconstruct:", np.round(B @ lam, 6))
print("Parseval: |x|^2 =", float(x @ x), " sum lam^2 =", float((lam ** 2).sum()))
 
# Exercise 3.8: Gram-Schmidt
p1 = np.array([1.0, 1.0, 1.0])
p2 = np.array([-1.0, 2.0, 0.0])
u1 = p1.copy()
coeff = float(u1 @ p2) / float(u1 @ u1)
u2 = p2 - coeff * u1
print("coefficient:", coeff, " u2 =", u2, " <u1,u2> =", float(u1 @ u2))
c1, c2 = u1 / np.linalg.norm(u1), u2 / np.linalg.norm(u2)
print("||u2|| =", np.linalg.norm(u2), " sqrt(42)/3 =", np.sqrt(42) / 3)
print("c2 * sqrt(42) =", np.round(c2 * np.sqrt(42), 6))
C = np.stack([c1, c2], axis=1)
print("C^T C =\n", np.round(C.T @ C, 15))
output
B^T B =
 [[ 1. -0.]
 [-0.  1.]]
coordinates: [1.414214 2.828427]
reconstruct: [ 3. -1.]
Parseval: |x|^2 = 10.0  sum lam^2 = 9.999999999999998
coefficient: 0.3333333333333333  u2 = [-1.33333333  1.66666667 -0.33333333]  <u1,u2> = 1.6653345369377348e-16
||u2|| = 2.1602468994692865  sqrt(42)/3 = 2.160246899469287
c2 * sqrt(42) = [-4.  5. -1.]
C^T C =
 [[1. 0.]
 [0. 1.]]

Note the two residues of floating point. Parseval gives 9.9999999999999989.999999999999998 rather than 1010, and u1,u2\langle\mathbf{u}_1,\mathbf{u}_2\rangle is 1.67×10161.67\times10^{-16} rather than 00. Both are one or two units in the last place — the correct amount of disagreement for a computation involving a square root, not an error to chase.

The first sketch is the skewed-axes intuition, made numeric. Drag the second basis vector towards the first and watch the coordinate readings interfere; drag it perpendicular and they stop.

sketch Reading coordinates off leaning axes p5.js
Drag b2. The white point x is fixed. The amber and blue segments are its coordinates in the basis (b1, b2), obtained by solving. When b2 is perpendicular to b1 the coordinates equal the plain inner products, shown alongside; as b2 leans towards b1 the two diverge and the condition number climbs.

The second sketch is Gram-Schmidt with a draggable input. The grey shadow is the part being subtracted.

sketch Gram-Schmidt: subtract the shadow, keep the rest p5.js
u1 is fixed as b1. Drag b2 anywhere. The grey arrow is the projection of b2 onto u1 — the part of b2 that already points along u1 — and u2 is what is left after removing it. The readout confirms the inner product of u1 with u2 is zero for every position of b2, and the normalised pair is drawn on the unit circle.

And the stepped version, on the book’s own Exercise 3.8:

vectorExercise 3.8, step by stepGram-Schmidt, §3.8.3
b1b2
dim U 0ambient R^3
setup2 vectors that span the subspace but are not orthogonal to each other. Gram-Schmidt keeps the first one and repairs each of the others in turn, by subtracting off whatever part of it already points along the ones already accepted.
1/5

Two vectors spanning a plane in three dimensions, turned into an orthonormal pair. The final frame shows the Gram matrix, which is the identity.

Two implementations that differ by one word, and the difference decides whether the output is usable:

gram_schmidt_two_ways.py
import numpy as np
 
def classical_gs(A):
    """Every coefficient taken against the ORIGINAL column."""
    n, m = A.shape
    Q = np.zeros((n, m))
    for j in range(m):
        v = A[:, j].copy()
        for i in range(j):
            v = v - (Q[:, i] @ A[:, j]) * Q[:, i]     # <- A[:, j]
        Q[:, j] = v / np.linalg.norm(v)
    return Q
 
def modified_gs(A):
    """Every coefficient taken against the RUNNING remainder."""
    n, m = A.shape
    Q = np.zeros((n, m))
    for j in range(m):
        v = A[:, j].copy()
        for i in range(j):
            v = v - (Q[:, i] @ v) * Q[:, i]           # <- v
        Q[:, j] = v / np.linalg.norm(v)
    return Q
 
def conditioned(n, kappa, seed=5):
    """A matrix with exactly the requested condition number."""
    rng = np.random.default_rng(seed)
    U, _ = np.linalg.qr(rng.normal(size=(n, n)))
    V, _ = np.linalg.qr(rng.normal(size=(n, n)))
    return U @ np.diag(np.logspace(0.0, -np.log10(kappa), n)) @ V.T
 
n = 8
print(f"{'kappa':>8} {'classical':>12} {'modified':>12} {'Householder':>12}")
for kappa in (1e2, 1e6, 1e10, 1e14):
    A = conditioned(n, kappa)
    row = []
    for Q in (classical_gs(A), modified_gs(A), np.linalg.qr(A)[0]):
        row.append(np.linalg.norm(Q.T @ Q - np.eye(n), 2))
    print(f"{kappa:8.0e} {row[0]:12.3e} {row[1]:12.3e} {row[2]:12.3e}")
print("machine epsilon:", np.finfo(float).eps)
output
   kappa    classical     modified  Householder
   1e+02    1.152e-13    9.622e-15    7.239e-16
   1e+06    3.063e-06    9.114e-11    7.334e-16
   1e+10    1.013e+00    2.507e-07    5.774e-16
   1e+14    2.993e+00    2.906e-03    1.052e-15
machine epsilon: 2.220446049250313e-16

Read the third row. At condition number 101010^{10}, classical Gram-Schmidt returns a matrix whose QQI\lVert\mathbf{Q}^\top\mathbf{Q} - \mathbf{I}\rVert is 1.0131.013 — the columns are not approximately orthonormal, they are not orthonormal at all. At 101410^{14} it reaches 2.9932.993, and since I2=1\lVert\mathbf{I}\rVert_2 = 1 that means the error is three times the size of the thing it was supposed to be.

Modified Gram-Schmidt — the same algorithm with the projection coefficient taken against the running remainder rather than the original column — is seven orders of magnitude better at κ=1010\kappa = 10^{10}. Householder QR, which is what np.linalg.qr runs, never leaves machine precision at all: its worst value across the whole sweep is 1.052×10151.052\times10^{-15}, under five units in the last place.

The mathematics of §3.8.3 is exact. The arithmetic is not, and this is the gap.

figure Three routes to the same orthonormal basis matplotlib
A log-log plot of loss of orthogonality against condition number for three algorithms. Classical Gram-Schmidt rises steeply and flattens near one; modified Gram-Schmidt rises more slowly; Householder QR stays flat at machine epsilon across the whole range. A log-log plot of loss of orthogonality against condition number for three algorithms. Classical Gram-Schmidt rises steeply and flattens near one; modified Gram-Schmidt rises more slowly; Householder QR stays flat at machine epsilon across the whole range.
Classical Gram-Schmidt degrades roughly like epsilon times the square of the condition number — the dashed reference line — and saturates once orthogonality is entirely lost. Its worst value here is 2.99e+00 against Householder's 1.05e-15.
figure Parseval holds, or it does not matplotlib
Two bar charts of squared coordinates. Under the orthonormal basis the bars sum to the squared length of the vector; under a skewed basis of the same subspace they sum to nearly twice as much. Both panels report a reconstruction error at machine precision. Two bar charts of squared coordinates. Under the orthonormal basis the bars sum to the squared length of the vector; under a skewed basis of the same subspace they sum to nearly twice as much. Both panels report a reconstruction error at machine precision.
The same vector expanded in two bases that span the same subspace. Both reconstruct it to machine precision, so both are correct expansions. Only the orthonormal one has squared coordinates that add up to 5.845617 — the skewed basis reports 11.526946, a gap of 5.6813.

From the orthogonality plot. Three things.

The classical curve tracks εκ2\varepsilon\kappa^2 — the dashed reference — rather than εκ\varepsilon\kappa. Squaring the condition number is what forming inner products against the original columns costs you, and it is the same squaring that makes the book’s [B~B~B~][\tilde{\mathbf{B}}\tilde{\mathbf{B}}^\top \mid \tilde{\mathbf{B}}] route inadvisable in floating point: B~B~\tilde{\mathbf{B}}\tilde{\mathbf{B}}^\top has the square of B~\tilde{\mathbf{B}}‘s condition number before elimination even starts.

The classical curve then saturates near 11 and stops rising. That is not the error levelling off, it is the error running out of room: QQI\lVert\mathbf{Q}^\top\mathbf{Q} - \mathbf{I}\rVert cannot grow much past a small constant once the columns bear no relation to orthonormality. A flat tail here means total failure, not stability.

Householder is flat at the bottom, and flat for a different reason: it never forms an inner product between two nearly-parallel columns. It builds Q\mathbf{Q} as a product of reflections, each of which is exactly orthogonal by construction, so the orthogonality of the result does not depend on the conditioning of the input at all.

From the Parseval bars. Both panels report a reconstruction error at machine precision, which is the control: both bases genuinely represent the vector, and neither expansion is wrong. What differs is whether the coordinates are interpretable. Under the ONB the squared coordinates sum to 5.8456175.845617, which is x2\lVert\mathbf{x}\rVert^2 to within 8.88×10168.88\times10^{-16}. Under the skewed basis they sum to 11.52694611.526946 — nearly double — so any statement of the form “this component accounts for 30%30\% of the energy” is meaningless in that basis. The skewed basis here has condition number only 6.796.79, which is mild; the failure is not a numerical one, it is that Parseval simply is not true off an ONB.

That is the property PCA’s variance-explained percentages rest on, and it is why they are quoted for principal components and never for the columns of an arbitrary factor loading matrix.

basis typeGram matrix BB\mathbf{B}^\top\mathbf{B}coordinates of x\mathbf{x}costParseval?
generalfull, symmetric positive definite(BB)1Bx(\mathbf{B}^\top\mathbf{B})^{-1}\mathbf{B}^\top\mathbf{x}O(n3)O(n^3) solveno
orthogonaldiagonalbi,x/bi2\langle\mathbf{b}_i,\mathbf{x}\rangle / \lVert\mathbf{b}_i\rVert^2O(n2)O(n^2), no solvewith weights
orthonormalI\mathbf{I}bi,x\langle\mathbf{b}_i,\mathbf{x}\rangleO(n2)O(n^2), no solveyes
pch.quizTag Check your understanding
  1. What does an orthonormal basis buy you that a general basis does not?

    pch.quizShowAnswer

    B — Coordinates become independent inner products rather than the solution of a system, so adding a new orthonormal direction leaves every earlier coordinate untouched — which is what makes truncation graceful — It is not unique — Gram-Schmidt's answer depends on the input order, and QR's column signs are arbitrary. The span is identical by construction. What changes is that B-transpose B is the identity, so the middle factor of the coordinate formula disappears.

  2. Classical Gram-Schmidt at condition number 1e10 gives ||Q-transpose Q minus I|| = 1.013. What does that number mean?

    pch.quizShowAnswer

    B — Orthogonality is completely gone — the identity matrix itself has 2-norm 1, so an error of 1.013 is the same size as the thing being approximated — At 1e14 it reaches 2.993, three times the norm of the identity. The curve saturating near 1 is the error running out of room rather than levelling off. Householder QR on the same matrices never exceeds 1.052e-15.

  3. Parseval's identity fails for the skewed basis in the figure, but that basis reconstructs the vector to machine precision. What is the lesson?

    pch.quizShowAnswer

    B — Both expansions are correct; only the orthonormal one has coordinates whose squares are interpretable as shares of the total energy — which is why variance-explained percentages are quoted for principal components and not for arbitrary loadings — Its condition number is 6.79, which is mild, and the reconstruction error is 2.16e-15. The failure is structural rather than numerical: the squared coordinates sum to 11.53 against a squared length of 5.85.

  4. A basis satisfies only Equation 3.33 — pairwise orthogonal, but not unit length. What breaks?

    pch.quizShowAnswer

    B — The coordinate formula: lambda-i is the inner product divided by the squared length of the basis vector, not the plain inner product, so B-transpose x is wrong by a per-coordinate factor — The Gram matrix is diagonal rather than the identity, so the middle factor of the coordinate formula is a diagonal inverse rather than nothing. The division appears explicitly in the Gram-Schmidt formula for exactly this reason.

Exercise 1 – Verify Example 3.8 and use it

Section titled “Exercise 1 – Verify Example 3.8 and use it”

Exercise 2 – Gram-Schmidt on the book’s Exercise 3.8

Section titled “Exercise 2 – Gram-Schmidt on the book’s Exercise 3.8”

Exercise 3 – Watch classical Gram-Schmidt fail

Section titled “Exercise 3 – Watch classical Gram-Schmidt fail”
  • An orthonormal basis is pairwise orthogonal and unit length — Definition 3.9’s two equations, which together say the Gram matrix B-transpose B is the identity.
  • Coordinates become inner products: lambda equals B-transpose x, one independent inner product per basis vector, with no system to solve.
  • Adding a new orthonormal direction leaves every earlier coordinate unchanged, which is what makes truncation graceful in Fourier series, wavelets and PCA.
  • Parseval’s identity holds only for an orthonormal basis: the squared coordinates add up to the squared length. Measured off an ONB the sum was 11.53 against a squared length of 5.85, on a well-conditioned basis.
  • Gram-Schmidt subtracts the projection onto everything already accepted and normalises. Its output depends on the input order, because the first vector survives unchanged.
  • Do not implement classical Gram-Schmidt. At condition number ten to the tenth it returns columns that are not orthonormal at all; modified Gram-Schmidt is seven orders better and Householder QR never leaves machine precision.
  • Forming B-transpose B squares the condition number, which is why both classical Gram-Schmidt and the augmented-matrix route lose accuracy where a Householder factorisation does not.
  • The projection formula collapses to B B-transpose for an orthonormal basis, and that collapse is what section 3.8 spends most of its time earning.

Next: Orthogonal Complement — what happens to everything the basis misses.

pch.coffeeTagline

pch.coffeeCta

pch.feedbackHeading

pch.feedbackSubheading