A lightweight, dependency-free JavaScript library that fills the
gaps the native Math object leaves behind. Statistics, number theory, and numeric
helpers in under 1 kb.
The native Math
object in JavaScript covers basic operations like rounding, trigonometry, and powers. But it
leaves gaps that nearly every project eventually runs into: statistical aggregates, percentile lookups, number theory basics like
GCD and LCM, and safe numeric clamping.
The common workarounds are to either write those helpers inline over and over, or pull in a large library like math.js that brings far more surface area than the project needs. One approach wastes time and invites bugs through repetition. The other bloats your bundle.
Maths.js sits between those two extremes: small enough to
drop into any project (under 1 kb gzipped), complete enough to cover the methods that actually
come up in application work, and strict enough to throw clear errors instead of silently
returning NaN when
something goes wrong.
Drop it in anywhere. Dashboards, data scripts, static pages. Without adding meaningful weight to your bundle.
Every method throws typed
TypeError or RangeError with clear messages instead of silently
returning NaN.
Works in browser via
<script> tag or in Node.js via require() with no build step
and no transitive packages.
Tests use Node's native node:test
module. Run them with node --test Maths.test.js, no extra dev dependencies.
npm
npm install @peterbenoit/mathsjs
CDN (jsDelivr)
<script src="https://cdn.jsdelivr.net/npm/@peterbenoit/mathsjs/Maths.js"></script>
Clone
git clone https://github.com/peterbenoit/Maths.js.git
Node.js
const Maths = require('@peterbenoit/mathsjs');
Maths.avg(10, 20, 30); // 20
Maths.median(7, 1, 4); // 4
Maths.gcd(48, 18); // 6
Browser (script tag)
<script src="/path/to/Maths.js"></script>
<script>
Maths.sum(1, 2, 3); // 6
Maths.clamp(12, 0, 10); // 10
</script>
Attaches to globalThis.Maths in browser
contexts. No bundler or build step needed.
All methods are static on the Maths object.
No instantiation required.
| Method | Description | Returns |
|---|---|---|
avg(...values) |
Arithmetic mean of all provided values | number |
sum(...values) |
Total of all provided values | number |
| Method | Description | Returns |
|---|---|---|
median(...values) |
Middle value; mean of two middle values for even-length inputs | number |
mode(...values) |
Most frequently occurring value(s); null
when all values are unique |
number[] | null |
range(...values) |
Difference between max and min | number |
percentile(values, p) |
Value at the pth percentile (0–100) | number |
| Method | Description | Returns |
|---|---|---|
factorial(n) |
Product of all positive integers up to n | number |
gcd(a, b) |
Greatest common divisor of two integers | number |
lcm(a, b) |
Least common multiple of two integers | number |
| Method | Description | Returns |
|---|---|---|
clamp(value, min, max) |
Constrains a value to the range [min, max] | number |
distance(x1, y1, x2, y2) |
Euclidean distance between two 2D points | number |
Statistics
Maths.avg(10, 20, 30); // 20
Maths.median(1, 3, 2); // 2
Maths.median(1, 2, 3, 4); // 2.5
Maths.mode(1, 2, 2, 3); // [2]
Maths.mode(1, 1, 2, 3, 3); // [1, 3]
Maths.mode(1, 2, 3); // null
Maths.range(1, 8, 3); // 7
Maths.percentile([1,2,3,4,5], 90); // 5
Number Theory
Maths.factorial(5); // 120
Maths.factorial(0); // 1
Maths.gcd(48, 18); // 6
Maths.gcd(100, 75); // 25
Maths.lcm(4, 6); // 12
Maths.lcm(7, 0); // 0
Utility
Maths.clamp(12, 0, 10); // 10
Maths.clamp(-5, 0, 10); // 0
Maths.clamp(7, 0, 10); // 7
Maths.distance(0, 0, 3, 4); // 5
Maths.distance(1, 1, 4, 5); // 5
Maths.js validates all inputs and throws typed errors
with descriptive messages. No silent NaN returns, no swallowed exceptions.
| Error type | When thrown |
|---|---|
TypeError |
Non-numeric input, non-finite number, non-integer where integer required, or wrong argument type |
RangeError |
Empty input, p outside [0, 100],
n < 0 for factorial, or min > max for clamp
|
try {
Maths.avg();
} catch (e) {
e instanceof RangeError; // true
e.message; // "avg requires at least one numeric value."
}
try {
Maths.factorial(-1);
} catch (e) {
e instanceof RangeError; // true
e.message; // "n must be a non-negative integer."
}
variance / stdDev. Population and sample variance
iqr and mad
compute interquartile range and median absolute deviation
nCr and nPr
calculate combinations and permutations
roundTo. Precision-safe rounding
zScore / normalize. Standard score and normalization
Suggestions welcome. Open an issue or PR on GitHub.
One import, eleven methods, zero dependencies. Covers the math that comes up in real projects without pulling in a full symbolic algebra system.