Skip to main content

math.js vs numeric.js vs stdlib: Math and Scientific Computing in JavaScript (2026)

·PkgPulse Team

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

Featuremath.jsnumeric.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~60KBModular

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 →

Comments

Stay Updated

Get the latest package insights, npm trends, and tooling tips delivered to your inbox.