Written and maintained by CASRAI Editorial Board
Last updated
In R, solve() does two jobs: it solves a linear system A x = b, and, when you leave out b, it returns the inverse of A. For a nonlinear equation f(x) = 0 you use uniroot() instead, and for an overdetermined or rank-deficient system you use qr.solve(). This guide shows each route with a small example whose answer you can check by hand, and explains which one fits which problem.
What it is used for in research
Four different tasks hide behind the phrase “solve in R”, and each has its own function:
- Square linear system (as many independent equations as unknowns):
solve(a, b)from base R. Typical uses are working through the normal equations of a regression by hand, checking a textbook calculation, or solving a small model with simultaneous equations. - Matrix inverse:
solve(a). The manual states that whenbis missing it is taken to be an identity matrix andsolvereturns the inverse ofa. - Single nonlinear equation, such as finding the x at which a fitted curve crosses a threshold:
uniroot()from the stats package. - Least squares or rank-deficient systems:
qr.solve(). The manual says the QR route handles over- and under-determined systems, providing a least-squares fit if appropriate.
Install or access
All three functions ship with R itself, so there is nothing to install beyond R. Download R from the Comprehensive R Archive Network at cran.r-project.org. solve() and qr.solve() live in the base package and uniroot() in the stats package; both load automatically in a normal session. To read the manual page for any of them from inside R, type ?solve, ?qr.solve or ?uniroot.
Step-by-step
1. Solve a linear system with solve(a, b)
Take the system 3x + 2y = 12 and x + 4y = 14. Its solution, worked by substitution, is x = 2 and y = 3. In R, put the coefficients in a matrix A and the right-hand sides in a vector b:
A <- matrix(c(3, 2,
1, 4), nrow = 2, byrow = TRUE)
b <- c(12, 14)
x <- solve(A, b)
x
The call returns the vector (2, 3). Check any answer by multiplying back: A %*% x should reproduce b. Note byrow = TRUE: without it, matrix() fills column by column, which silently builds the transposed system and gives a different, wrong answer.
2. Get the inverse by leaving out b
solve(A)
For the same matrix the determinant is 3 × 4 − 2 × 1 = 10, so the inverse is the matrix with rows (0.4, −0.2) and (−0.1, 0.3). Compute an explicit inverse only when you need the inverse itself, for example for a covariance matrix of coefficients. To get a solution for one right-hand side, solve(A, b) is the direct call and avoids forming the inverse first.
3. Find the root of f(x) with uniroot()
To solve x² − 2 = 0 on the interval from 0 to 2 (the answer is the square root of 2, about 1.41421):
f <- function(x) x^2 - 2
r <- uniroot(f, interval = c(0, 2))
r$root
r$f.root
r$iter
r$estim.prec
The root you get is correct only to the stopping tolerance, not to full machine precision, as explained in the next section.
4. Fit a least-squares solution with qr.solve()
If A has more rows than columns (more equations than unknowns), no exact solution generally exists. qr.solve(A, b) returns the least-squares solution, the same quantity a linear regression of b on the columns of A estimates. The manual notes that qr.solve() takes tol = 1e-7 by default.
Output and how to read it
solve() output
With b supplied you get a vector (or matrix, if b is a matrix) of solutions; without it you get the inverse matrix. The tol argument is "the tolerance for detecting linear dependencies in the columns of a". The older LINPACK argument is listed as defunct and an error, so do not pass it.
Floating-point noise
Results are computed in floating point, so an answer that is exactly 4 on paper can print as 3.999999999999999 or carry a tiny residue such as 1e-16 where you expected 0. Compare with all.equal() instead of ==, and use zapsmall() to round away residue when you display a matrix. Both are base R functions.
uniroot() output
The result is a list with four fields that matter:
root: the estimated location of the root.f.root: the function value at that root. It should be close to zero; check it.iter: how many iterations were used.estim.prec: according to the manual, an approximate estimated precision for the root (NAif the root falls exactly on an endpoint, per the manual).
The manual says convergence is declared either if f(x) is exactly zero or if the change in x for one step of the algorithm is less than tol. The default is tol = .Machine$double.eps^0.25, which is about 0.00012, so the default root is good to roughly four decimal places. For a published result, tighten it, for example uniroot(f, c(0, 2), tol = 1e-10), and report f.root.
Which function for which problem
| Problem | Function | Condition stated in the manual |
|---|---|---|
| Square linear system, or inverse of a matrix | solve(a, b) / solve(a) |
a is a square numeric or complex matrix of coefficients |
| More equations than unknowns, or rank-deficient | qr.solve(a, b) |
Handles over- and under-determined systems, giving a least-squares fit where appropriate |
| One nonlinear equation f(x) = 0 | uniroot(f, interval) |
Function values at the interval endpoints must have opposite signs (or be zero) with the default extendInt = "no" |
Troubleshooting
solve() fails on a singular matrix
This means the columns of A are linearly dependent (or nearly so), so the matrix has no usable inverse. The manual notes that unsuccessful results from the underlying LAPACK code produce an error giving a positive error code. A two-by-two example is the matrix with rows (1, 2) and (2, 4): the second row is twice the first. In research data the usual cause is perfectly collinear predictors; see perfect multicollinearity and the variance inflation factor guide for how to find and remove the redundant column. If the system is legitimately overdetermined, switch to qr.solve().
Non-conformable or wrong-length b
Each element of b is the right-hand side of one equation, so its length (or number of rows, for a matrix) must equal the number of rows of A. Count equations and unknowns before calling solve(), and confirm A is square with dim(A).
uniroot() stops with an error about the endpoints
The default requires f(lower) and f(upper) to have opposite signs, so a sign change must lie inside the interval. Plot the function over a wide range first, then choose an interval that brackets the crossing. The manual also documents extendInt ("no", "yes", "downX", "upX"), which lets uniroot() widen the interval itself. A function with no real root, such as x² + 1, has no sign change at all, and no interval will work.
The answer looks slightly off
If the root from uniroot() disagrees with your hand calculation in the fifth decimal, that is the default tol at work, not a bug. Lower tol and compare estim.prec.
Free alternatives
These are the built-in routes, all free with base R:
| Task | Base R function | Package |
|---|---|---|
| Linear system or inverse | solve() |
base |
| Least squares / rank-deficient systems | qr.solve() |
base |
| Single-variable root finding | uniroot() |
stats |
If you want to see least squares at work on real data rather than raw matrices, the linear regression calculator guide shows the same quantities in R, and running a t-test in R is a good next step for hypothesis testing.
FAQ
What does solve() do in R?
It solves a system of linear equations A x = b for a square coefficient matrix A. If you omit b, it returns the inverse of A.
How do I solve an equation like x^2 - 2 = 0 in R?
Use uniroot() with a function and an interval whose endpoints give opposite signs. solve() does not handle nonlinear equations.
How do I get the inverse of a matrix in R?
Call solve(A) with one argument. Check it by confirming that A %*% solve(A) is close to the identity matrix, using zapsmall() to hide floating-point residue.
What if my system has more equations than unknowns?
Use qr.solve(), which returns a least-squares fit for over-determined systems.
Why is my answer 3.9999999 instead of 4?
Floating-point arithmetic. Compare with all.equal() and round for display; do not test equality with ==.
For more statistical software guides, see the power analysis in R guide.
Sources
- R Documentation, solve: Solve a System of Equations (base package), stat.ethz.ch/R-manual/R-devel/library/base/html/solve.html, checked 2026-10-29.
- R Documentation, uniroot: One Dimensional Root (Zero) Finding (stats package), stat.ethz.ch/R-manual/R-devel/library/stats/html/uniroot.html, checked 2026-10-29.
- R Documentation, qr: The QR Decomposition of a Matrix (includes
qr.solve), stat.ethz.ch/R-manual/R-devel/library/base/html/qr.html, checked 2026-10-29. - The Comprehensive R Archive Network, cran.r-project.org.








