C++
Matrix Determinant
Algorithm
Linear Algebra
Programming

Matrix determinant algorithm C

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

For real code, the best determinant algorithm is not recursive expansion by minors. The practical choice is Gaussian elimination with row swaps, because it runs in cubic time and scales to matrices that would make a Laplace expansion unusably slow.

Why elimination is the standard algorithm

The determinant changes in predictable ways under row operations. Swapping two rows flips the sign, multiplying a row by a constant scales the determinant, and subtracting a multiple of one row from another leaves the determinant unchanged.

Gaussian elimination uses those properties to transform the matrix into upper-triangular form. Once the matrix is triangular, the determinant is just the product of the diagonal entries, adjusted for any row swaps.

A practical C++ implementation

The following code computes a determinant using elimination with partial pivoting. It copies the matrix so the original input remains unchanged.

cpp
1#include <cmath>
2#include <iostream>
3#include <vector>
4
5double determinant(std::vector<std::vector<double>> matrix) {
6    const int n = static_cast<int>(matrix.size());
7    int sign = 1;
8    double det = 1.0;
9
10    for (int col = 0; col < n; ++col) {
11        int pivot = col;
12        for (int row = col + 1; row < n; ++row) {
13            if (std::fabs(matrix[row][col]) > std::fabs(matrix[pivot][col])) {
14                pivot = row;
15            }
16        }
17
18        if (std::fabs(matrix[pivot][col]) < 1e-12) {
19            return 0.0;
20        }
21
22        if (pivot != col) {
23            std::swap(matrix[pivot], matrix[col]);
24            sign *= -1;
25        }
26
27        const double pivot_value = matrix[col][col];
28        det *= pivot_value;
29
30        for (int row = col + 1; row < n; ++row) {
31            const double factor = matrix[row][col] / pivot_value;
32            for (int k = col; k < n; ++k) {
33                matrix[row][k] -= factor * matrix[col][k];
34            }
35        }
36    }
37
38    return det * sign;
39}
40
41int main() {
42    std::vector<std::vector<double>> matrix = {
43        {2.0, 1.0, 3.0},
44        {1.0, 0.0, 2.0},
45        {4.0, 1.0, 8.0}
46    };
47
48    std::cout << determinant(matrix) << '\n';
49}

Partial pivoting makes the algorithm more numerically stable than blindly dividing by the current diagonal entry. It also prevents simple zero-pivot failures when another row can be swapped into place.

Why not recursive cofactors

Laplace expansion is fine for teaching the definition of the determinant or for tiny matrices such as 2 x 2 and 3 x 3. For larger inputs, its cost grows far too quickly. It is a mathematical definition, not the implementation you want in production.

That is why most serious numerical libraries use elimination-based methods or factorizations such as LU decomposition rather than cofactor recursion.

Implementation considerations

This code assumes the matrix is square and stored densely. If your program works with integer matrices and needs exact arithmetic, floating-point elimination can introduce rounding error, so the implementation strategy may need to change. For scientific or engineering work, double is usually a practical default, but tolerance checks still matter near singular matrices.

Common Pitfalls

  • Implementing recursive minors for anything beyond tiny matrices and then hitting terrible performance.
  • Forgetting that row swaps change the sign of the determinant.
  • Dividing by a near-zero pivot without pivoting and getting unstable results.
  • Modifying the original matrix unintentionally when the caller still needs it.
  • Using determinant computation as a generic test for everything when solving or factorizing the matrix directly may be more useful.

Summary

  • The practical determinant algorithm is Gaussian elimination with pivoting.
  • Convert the matrix to upper-triangular form and multiply the diagonal entries.
  • Track row swaps because each swap flips the determinant sign.
  • Recursive cofactor expansion is educational, not efficient.
  • For serious numerical work, elimination-based methods are the correct baseline.

Course illustration
Course illustration

All Rights Reserved.