Skip to main content
v2026.11,858 entries · CC-BY 4.0

Solve in R: solve(), qr.solve() and uniroot() Explained

How to solve in R: solve(a, b) for linear systems and inverses, qr.solve() for least squares, uniroot() for f(x) = 0, with checks you can do by hand.

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 when b is missing it is taken to be an identity matrix and solve returns the inverse of a.
  • 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 (NA if 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

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about Solve in R: solve(), qr.solve() and uniroot() Explained

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →

Ask CASRAI · Regulatory Radar

Research-admin question? Get an answer that links its sources.

An AI assistant specialized in research administration. Every answer links its sources to check before you act. 2 questions free, no account. $29/month after.

  • Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.
  • Every answer numbers its sources and links each one, so you can check the source yourself.