math.js vs numeric.js vs stdlib: Math and Scientific Computing in JavaScript (2026)
TL;DR
math.js is the most popular and comprehensive math library for JavaScript — supports symbolic math, complex numbers, matrices, units, and a full expression parser. numeric.js focuses on numerical analysis and linear algebra — matrix operations, SVD, eigenvalues. @stdlib/stdlib is a full scientific computing library modeled after NumPy/SciPy — modular, tree-shakable, and growing fast. For a versatile all-around math library: math.js. For numerical linear algebra: numeric.js or mathjs matrices. For NumPy-like scientific computing with statistics: @stdlib/stdlib.
Key Takeaways
- math.js: ~4M weekly downloads — expression parser, matrices, complex numbers, units, bignumber support
- numeric.js: ~700K weekly downloads — focused on numerical methods, matrix decompositions
- @stdlib/stdlib: ~5M weekly downloads (modular packages) — NumPy-like, statistics, distributions
- math.js can be used both as a library and as an expression evaluator (parsing math strings)
- @stdlib is tree-shakable — install individual packages (
@stdlib/math-base-special-gamma) - For most visualization/chart libraries: math.js handles common statistical needs
math.js
math.js — the all-around JavaScript math library:
Basic arithmetic and algebra
import { create, all } from "mathjs"
const math = create(all)
// Basic operations:
math.add(2, 3) // 5
math.subtract(10, 4) // 6
math.multiply(3, 4) // 12
math.divide(15, 4) // 3.75
// Advanced math:
math.sqrt(144) // 12
math.pow(2, 10) // 1024
math.log(math.E) // 1
math.log(100, 10) // 2 (log base 10)
math.sin(math.pi / 2) // 1
math.factorial(10) // 3628800
// Constants:
math.pi // 3.141592653589793
math.e // 2.718281828459045
math.phi // 1.618033988749895 (golden ratio)
math.i // Complex number i
Expression parser
import { evaluate, compile } from "mathjs"
// Parse and evaluate math strings (useful for calculators, formulas):
evaluate("2 + 3") // 5
evaluate("sqrt(144)") // 12
evaluate("sin(pi/2)") // 1
evaluate("log(e)") // 1
// With variables:
evaluate("x^2 + y^2", { x: 3, y: 4 }) // 25 (Pythagorean: 9 + 16)
// Compile for repeated evaluation (faster):
const expr = compile("a * b + c")
expr.evaluate({ a: 2, b: 3, c: 4 }) // 10
expr.evaluate({ a: 5, b: 5, c: 0 }) // 25
// Useful for user-defined formulas in apps:
function calculateCustomMetric(formula: string, data: Record<string, number>) {
try {
return evaluate(formula, data)
} catch {
throw new Error(`Invalid formula: ${formula}`)
}
}
// User enters: "downloads * 0.5 + stars * 0.3 + score * 0.2"
calculateCustomMetric(
"downloads * 0.5 + stars * 0.3 + score * 0.2",
{ downloads: 45, stars: 200, score: 95 }
)
// 22.5 + 60 + 19 = 101.5
Matrices
import { matrix, multiply, transpose, inv, det, eigs } from "mathjs"
// Create matrices:
const A = matrix([[1, 2], [3, 4]])
const B = matrix([[5, 6], [7, 8]])
// Operations:
multiply(A, B) // [[19, 22], [43, 50]]
transpose(A) // [[1, 3], [2, 4]]
inv(A) // Inverse: [[-2, 1], [1.5, -0.5]]
det(A) // Determinant: -2
// Eigenvalues/eigenvectors:
const { values, vectors } = eigs(A)
// values: [-0.37228, 5.37228]
// Solving linear systems Ax = b:
import { lusolve } from "mathjs"
const coefficients = [[2, 1], [1, 3]]
const constants = [8, 13]
const solution = lusolve(coefficients, constants)
// [[3], [2]] → x=3, y=2 for: 2x + y = 8, x + 3y = 13
Statistics
import { mean, median, std, variance, min, max, quantileSeq } from "mathjs"
const data = [4, 8, 6, 5, 3, 2, 8, 9, 2, 5]
mean(data) // 5.2
median(data) // 5 (sorted: 2,2,3,4,5,5,6,8,8,9 → median = (5+5)/2)
std(data) // 2.44... (standard deviation)
variance(data) // 5.955... (variance)
min(data) // 2
max(data) // 9
// Percentiles:
quantileSeq(data, 0.25) // 25th percentile (Q1)
quantileSeq(data, 0.75) // 75th percentile (Q3)
Units and complex numbers
import { unit, complex, add, abs, arg } from "mathjs"
// Physical units:
const speed = unit("100 km/h")
speed.toNumber("m/s") // 27.78
unit("9.8 m/s^2").to("km/h^2") // Unit conversion
// Complex numbers:
const z1 = complex(3, 4) // 3 + 4i
const z2 = complex(1, 2) // 1 + 2i
add(z1, z2) // 4 + 6i
abs(z1) // 5 (magnitude: √(3²+4²))
arg(z1) // 0.9273 radians (angle)
numeric.js
numeric.js — focused on numerical linear algebra:
Matrix operations and decompositions
import numeric from "numeric"
// Matrix creation:
const A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
const b = [1, 2, 3]
// Basic operations:
numeric.add(A, A) // Element-wise addition
numeric.mul(A, 2) // Scalar multiplication
numeric.dot(A, b) // Matrix-vector product
numeric.transpose(A) // Transpose
// Solve Ax = b (linear system):
const x = numeric.solve(A, b)
// LU decomposition:
const lu = numeric.LU(A)
// SVD (Singular Value Decomposition):
const svd = numeric.svd(A)
// { S: singular values, U: left vectors, V: right vectors }
// Eigenvalues (symmetric matrix):
const eig = numeric.eig([[4, 2], [2, 4]])
// { lambda: eigenvalues, E: eigenvectors }
Optimization
import numeric from "numeric"
// Gradient descent (unconstrained minimization):
// Find minimum of f(x) = (x-3)² + (y-5)²
function objective(x: number[]) {
return Math.pow(x[0] - 3, 2) + Math.pow(x[1] - 5, 2)
}
function gradient(x: number[]) {
return [2 * (x[0] - 3), 2 * (x[1] - 5)]
}
// Note: numeric.js uses uncmin for unconstrained minimization
const result = numeric.uncmin(objective, [0, 0])
// result.solution ≈ [3, 5] (the minimum)
@stdlib/stdlib
@stdlib/stdlib — NumPy/SciPy-inspired scientific computing:
Installation and usage (modular packages)
// @stdlib is highly modular — install only what you need:
// npm install @stdlib/stats-base-mean @stdlib/math-base-special-gamma
// Or the full library:
// npm install @stdlib/stdlib
// Statistical distributions:
import * as norm from "@stdlib/stats-base-dists-normal"
const mu = 0 // mean
const sigma = 1 // standard deviation
norm.pdf(0, mu, sigma) // 0.3989 (probability density at x=0)
norm.cdf(1.96, mu, sigma) // 0.975 (cumulative: 97.5% below z=1.96)
norm.quantile(0.95, mu, sigma) // 1.645 (95th percentile)
// Random sampling:
import normal from "@stdlib/random-base-normal"
const rnorm = normal.factory(0, 1) // N(0,1) random number generator
const samples = Array.from({ length: 1000 }, rnorm)
Statistics
import mean from "@stdlib/stats-base-mean"
import variance from "@stdlib/stats-base-variance"
import skewness from "@stdlib/stats-base-skewness"
const data = new Float64Array([4, 8, 6, 5, 3, 2, 8, 9, 2, 5])
const n = data.length
mean(n, 1, data, 1) // 5.2 (stride=1)
variance(n, 1, mean(n, 1, data, 1), data, 1) // Variance with known mean
Special mathematical functions
// @stdlib provides the most complete set of special functions in JS:
import gamma from "@stdlib/math-base-special-gamma"
import beta from "@stdlib/math-base-special-beta"
import erf from "@stdlib/math-base-special-erf"
import bessel from "@stdlib/math-base-special-besselj0"
gamma(5) // 24 (4! = Gamma(5))
gamma(0.5) // 1.7724... (√π)
beta(2, 3) // 0.0833...
erf(1) // 0.8427... (error function)
bessel(0) // 1.0 (Bessel function J₀)
// These are not available in math.js or numeric.js
Feature Comparison
| Feature | math.js | numeric.js | @stdlib |
|---|---|---|---|
| Expression parser | ✅ | ❌ | ❌ |
| Symbolic math | ✅ | ❌ | ❌ |
| Matrices | ✅ | ✅ (specialized) | ✅ |
| Linear algebra | ✅ | ✅ Excellent | ✅ |
| Statistics | ✅ Basic | ✅ | ✅ Excellent |
| Distributions | ✅ | ❌ | ✅ Many |
| Special functions | ✅ Some | ❌ | ✅ Most complete |
| Random sampling | ✅ | ❌ | ✅ |
| Units | ✅ | ❌ | ❌ |
| Complex numbers | ✅ | ✅ | ✅ |
| BigNumber | ✅ | ❌ | ❌ |
| Tree-shakable | ⚠️ | ❌ | ✅ |
| TypeScript | ✅ | ✅ @types | ✅ |
| Bundle size | ~150KB | ~60KB | Modular |
When to Use Each
Choose math.js if:
- You need a user-facing expression evaluator (calculator, formula fields)
- Working with physical units and unit conversion
- Complex numbers, symbolic math, or BigNumber precision
- General-purpose math without needing the full scipy-like suite
Choose numeric.js if:
- Specific numerical analysis: SVD, eigenvalues, LU decomposition
- Solving linear systems at high performance
- Already using it in the codebase for its specialized algorithms
Choose @stdlib if:
- Scientific computing requiring statistical distributions (normal, Poisson, binomial)
- Special mathematical functions (Gamma, Beta, Bessel, error function)
- NumPy-style BLAS operations with typed arrays
- Tree-shaking matters — you can import only the functions you need
Consider TensorFlow.js for ML math:
// For machine learning operations (tensor math, GPU acceleration):
// @tensorflow/tfjs provides GPU-accelerated matrix operations
// Math.js/numeric.js are CPU-only — TF.js for ML pipelines
import * as tf from "@tensorflow/tfjs"
const matrix = tf.tensor2d([[1, 2], [3, 4]])
const result = tf.matMul(matrix, tf.transpose(matrix))
Methodology
Download data from npm registry (weekly average, February 2026). Feature comparison based on mathjs v13.x, numeric.js v1.x, and @stdlib/stdlib v0.3.x.
Compare math and scientific computing packages on PkgPulse →