Determinants
Signed area, invertibility, and why det = product of eigenvalues.
On this page
Beginner: the determinant is a single number computed from a square matrix that tells you how much the matrix's transformation scales area (in 2D) or volume (in 3D and beyond). A determinant of 2 means "everything doubles in area." A determinant of 0 means "everything gets squashed flat" — the transformation destroys a dimension.
Intermediate: the sign matters too, not just the size. A negative determinant means the transformation flips orientation — like a reflection in a mirror. This is why the determinant is "signed area/volume," not just plain area/volume.
Advanced: a matrix has an inverse if and only if its determinant is non-zero — this is the precise, computable version of the "singular vs. non-singular" language from section 1.6, and it's mathematically identical to saying the matrix has full rank (section 1.9). All three ideas — nonzero determinant, full rank, invertibility — are exactly the same fact viewed three different ways.
For larger matrices the formula generalizes recursively (cofactor expansion), but in practice no one computes determinants this way by hand past 3×3 — libraries use LU decomposition (section 1.13) instead, since the determinant of a triangular matrix is just the product of its diagonal.
Place two vectors a=(a₁,a₂) and b=(b₁,b₂) as the columns of a matrix — exactly the parallelogram in the diagram below. Decompose the parallelogram's area using the "base times height" formula, resolved into coordinates: the area equals the area of the bounding rectangle (a₁+b₁)(a₂+b₂) minus the four triangles/rectangles around it that aren't part of the parallelogram. Carrying out that bookkeeping (the classic "shoelace formula" derivation) collapses to exactly:
which is precisely |det[a\ b]| — the absolute value of the determinant of the matrix whose columns are a and b. Dropping the absolute value recovers the signed area: positive when b is counterclockwise from a, negative when clockwise — exactly the orientation flip shown in the diagram.
Where this is used: this signed-area interpretation generalizes directly to signed volume in 3D (and hypervolume in higher dimensions), which is exactly what makes the determinant the correct scaling factor in the change-of-variables formula used by normalizing flows (section 1.35).
Drag either vector — the shaded parallelogram's area is exactly |det|.
det(AB) = det(A)·det(B) always holds — composing two transformations multiplies their scaling factors, exactly as you'd expect.
#include <cstdio>
#include <vector>
using Matrix = std::vector<std::vector<double>>;
// Recursive cofactor expansion along the first row -- no linear-algebra library.
double determinant(const Matrix& M) {
int n = static_cast<int>(M.size());
if (n == 1) return M[0][0];
if (n == 2) return M[0][0] * M[1][1] - M[0][1] * M[1][0];
double total = 0.0;
for (int col = 0; col < n; ++col) {
Matrix minor;
for (int r = 1; r < n; ++r) {
std::vector<double> row;
for (int c = 0; c < n; ++c) {
if (c == col) continue;
row.push_back(M[r][c]);
}
minor.push_back(row);
}
double sign = (col % 2 == 0) ? 1.0 : -1.0;
total += sign * M[0][col] * determinant(minor);
}
return total;
}
Matrix matmul(const Matrix& A, const Matrix& B) {
int n = static_cast<int>(A.size());
int k = static_cast<int>(A[0].size());
int m = static_cast<int>(B[0].size());
Matrix C(n, std::vector<double>(m, 0.0));
for (int i = 0; i < n; ++i)
for (int j = 0; j < m; ++j)
for (int x = 0; x < k; ++x) C[i][j] += A[i][x] * B[x][j];
return C;
}
int main() {
Matrix A = {{3, 1}, {2, 4}};
std::printf("%.1f\n", determinant(A)); // 10.0
Matrix singular = {{1, 2}, {2, 4}};
std::printf("%.1f\n", determinant(singular)); // 0.0
Matrix B = {{0, -1}, {1, 0}}; // 90-degree rotation, det = 1
std::printf("%.4f %.4f\n", determinant(matmul(A, B)), determinant(A) * determinant(B));
return 0;
}- Change of variables in probability and statistics — transforming a probability distribution to a new coordinate system requires dividing by the absolute value of the transformation's Jacobian determinant (section 1.17), to keep total probability equal to 1.
- Fast invertibility checks — before attempting to invert a matrix or solve a system, checking
det ≈ 0flags a numerically dangerous problem early. - Computer graphics — the determinant of a 3×3 transformation matrix tells a renderer whether a triangle's winding order (and therefore which face is "front-facing") has flipped.
- Determinants are only defined for square matrices — there's no such thing as "the determinant" of a rectangular data matrix.
- Trusting
det(A) == 0exactly in floating point — real computations produce tiny non-zero values like1e-16for genuinely singular matrices. Compare against a small tolerance, or better, check the condition number (section 1.10) instead.
Going deeper
The determinant equals the product of a matrix's eigenvalues — this is why det(A − λI) = 0 (the characteristic equation from section 1.7) works at all: it's asking "for what λ does A − λI become singular (determinant zero)?"
At the master level: for large matrices, computing the raw determinant is numerically dangerous — it can overflow or underflow to zero even when the matrix is perfectly healthy, because it's a product of many numbers. Production code almost always works with the log-determinant instead (summing log|eigenvalues| or log of the diagonal of a Cholesky/LU factor), which is exactly how multivariate Gaussian log-likelihoods are computed in every serious statistics and ML library.
If det(A) = 0, what does that tell you about solving Ax = b?
A has no inverse, so the system either has no solution or infinitely many — you cannot solve it uniquely with A⁻¹.