bignumber.js: arbitrary-precision decimal arithmetic for JavaScript
A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic
At a glance
- What is it?
- bignumber.js replaces JavaScript's floating-point Number with an immutable decimal type, and it is the right tool when money, IDs or scientific values must not drift. It is also a library you have to configure before it matches your expectations.
- Who is it for?
- Adopt bignumber.js if you handle currency, ledger balances, or identifiers that exceed 15 significant digits, and you want a single 8 KB dependency with no transitive packages. Do not adopt it if you only need integer arithmetic within BigInt's range, or if you want a library that silently picks a precision for you.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 30 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The precision problem bignumber.js exists to solve
JavaScript's Number type is a 64-bit binary floating-point value. It cannot represent 0.1 exactly, and it only carries about 15 significant decimal digits. The README demonstrates both failures directly. `new BigNumber(0.7 + 0.1)` returns '0.7999999999999999', because the addition happens in binary floating point before the library ever sees the value. `new BigNumber(88259496234518.57)` returns '88259496234518.56'. And `new BigNumber(99999999999999999999)` returns '100000000000000000000'.
The audience is anyone whose numbers are not approximations: invoice totals, tax calculations, account balances, order quantities, unit prices, and identifiers such as database keys or transaction hashes that can exceed the safe integer range. If your code compares two monetary values with `===` after doing arithmetic on them, this library is aimed at you. The alternative that most people reach for first, BigInt, only covers integers, so it does not help with 0.1 + 0.2.
How BigNumber values are constructed and why the input type matters
The library exports a single constructor, `BigNumber`, which accepts a Number, String, BigInt or another BigNumber. The constructor is the whole design: everything else is methods on the resulting immutable value. The README states that a BigNumber is created from a Number's decimal `toString()` value, not from its underlying binary value. That detail explains the precision loss examples above, and it is the reason the documentation recommends creating BigNumbers from String values rather than Number values.
If you genuinely need the binary representation of a Number, the README gives the escape hatch: pass the Number's `toString(2)` value and specify base 2. BigNumbers can also be created from strings in bases 2 to 36, with `ALPHABET` available to extend that range. The README warns that explicitly passing base 10 is not recommended, because it forces the slower base conversion path, which is only necessary when an unconventional `ALPHABET` has been set.
Immutability is the other structural point. The README's example is `x.minus(0.1)` returning '0.2' while `x` itself remains '0.3'. Methods that return a BigNumber can be chained, so `x.dividedBy(y).plus(z).times(9)` is valid. This is a value-object model, not a mutable accumulator, and it means you cannot accidentally mutate a shared balance by passing it into a helper function.
Installing bignumber.js and running a first calculation
The package is on npm, and the README's Node.js section gives the install command directly. The package.json declares `main` as `dist/bignumber.cjs`, `module` as `dist/bignumber.mjs` and `browser` as `dist/bignumber.js`, with conditional `exports` mapping types for each format, so both `require` and `import` resolve to a real file without a bundler.
npm install bignumber.jsAfter installing, require the CommonJS build in a script. The README also shows importing from a local repo with `require('./dist/bignumber.cjs')`, which is useful if you are working against a checkout rather than the published package.
const BigNumber = require('bignumber.js');
let x = new BigNumber(123.4567);
let y = BigNumber('123456.7e-3');
let z = new BigNumber(x);
x.isEqualTo(y) && y.isEqualTo(z) && x.isEqualTo(z); // trueThe README notes that `let`, semicolons and `toString` calls are omitted from its later examples, and that a commented-out value in quotes means `toString` was called on the expression. That convention matters when you read the API docs, because many methods return a BigNumber rather than a string.
For output, use `toString()` or `toFixed()`. The README states that `toFixed()` prevents exponential notation from being returned no matter how large or small the value is.
let x = new BigNumber('1_234_567_890_000_000_000_000');
x.toString(); // "1.23456789e+21"
x.toFixed(); // "1234567890000000000000"Note the underscore separators inside the string literal. They are part of the input string the library parses, not a JavaScript numeric literal.
Build formats, browser loading and the Deno path
The repository has a single source file, `bignumber.js`, plus `bignumber.d.ts` for type declarations. The README describes `build.js` as the script that creates targeted builds in a `dist` directory for ES module, CommonJS and browser usage. Running it requires Node.js 14.14.0 or later, and the package.json scripts expose `npm run build` and `node build.js` as equivalents.
The build produces three distributables with matching declarations: `bignumber.mjs` with `bignumber.d.mts`, `bignumber.cjs` with `bignumber.d.cts`, and `bignumber.js` with `bignumber.d.ts`. The published package only ships `dist`, per the `files` field, so consumers never see the source file or the build script.
In a browser, the README shows a plain script tag pointing at `dist/bignumber.js`, or a minified build from jsDelivr. For ES modules it shows either a relative import of `./dist/bignumber.mjs` or jsDelivr's `+esm` endpoint. Deno users import from a raw GitHub URL or unpkg, with a `@deno-types` comment to attach the `.d.mts` declarations. That is four distinct loading paths, and the README documents all of them, which is more than most small libraries bother to do.
Rounding, configuration and the parts the README leaves to the docs site
The README's feature list mentions a correctly-rounded `squareRoot` method, a `toFraction` method, and support for cryptographically secure pseudo-random number generation. It also says the library replicates `toExponential`, `toFixed`, `toPrecision` and `toString` from the Number type. What the README does not do is explain the configuration object in any depth. There is a dedicated documentation site at mikemcl.github.io/bignumber.js, and the README links to it repeatedly, but the configuration options, the default rounding mode, the default decimal places, and the interaction between them are not spelled out in the README itself.
That is a real gap for a library whose entire purpose is controlling precision. A reader who installs bignumber.js and starts dividing without setting a rounding mode is relying on defaults they have not read. The README's own warning about passing base 10 explicitly shows the library is sensitive to how you call it, and the same care applies to rounding. Treat the documentation site as required reading, not optional.
The other stated limitation is platform reach. The README says the library uses JavaScript 1.5 (ECMAScript 3) features only, which is why it runs in old browsers, but it also means the API cannot rely on modern language features. The build script, by contrast, requires Node.js 14.14.0 or later. The runtime and the build toolchain have very different floors.
bignumber.js against big.js and decimal.js
The README names two alternatives directly, both by the same author. big.js is described as less than half the size but limited to decimal numbers, with about half the methods, fewer configuration options, and no support for `NaN` or `Infinity`. That last point is the sharpest difference: if your data can contain `NaN` or `Infinity`, big.js is not a drop-in replacement, regardless of size.
decimal.js is described as adding support for non-integer powers and performing all operations to a specified number of significant digits. That is a different precision model. bignumber.js works in terms of decimal places; decimal.js works in terms of significant digits. For financial arithmetic where you care about cents, decimal places map directly onto the problem. For scientific or engineering work where relative error is what matters, significant digits are the more natural unit, and decimal.js is the better fit.
The README's comparison to JavaScript ports of Java's BigDecimal is a size and speed claim, not a feature claim. It says bignumber.js is faster, smaller, and perhaps easier to use. Since that claim comes from the project itself and the README gives no benchmark numbers, treat it as a design goal rather than a measured result. The repository does contain a `perf/` directory, so there is a place where performance work happens, but the README does not publish results from it.
Maintenance, licence and what upgrading costs
The repository is not archived, and the last push was on 2026-08-31. The most recent release listed is v11.1.3 on 2026-04-30, while package.json in the repository declares version 11.1.5, so the repository is ahead of the last tagged release. There is a CHANGELOG.md at the top level, and the README's table of contents does not link to it, so release history lives in a file you have to open yourself rather than in the README.
The licence is MIT, declared in package.json and present as LICENCE.md. MIT is permissive: it allows commercial and closed-source use, and it requires that the copyright notice and permission notice be included in copies or substantial portions of the software. That is the standard obligation, not legal advice; check how your own distribution handles third-party notices.
Upgrade cost is low in one respect and non-trivial in another. The library has no dependencies, so there is no transitive tree to audit and no version conflict to resolve. The package ships only `dist`, and the `exports` map provides separate type declarations per module format, so TypeScript consumers get types without a `@types` package. The non-trivial part is behavioural: the README's own examples show that constructing from a Number versus a String changes the result, and that passing base 10 explicitly changes the code path. A major version bump that touches parsing or rounding would be felt in any code that relied on an unstated default. The devDependency is TypeScript ^5.1.6, used for four separate typecheck scripts covering CJS, ESM, global and API surfaces.
Editorial conclusion
Adopt bignumber.js if you handle currency, ledger balances, or identifiers that exceed 15 significant digits, and you want a single 8 KB dependency with no transitive packages. Do not adopt it if you only need integer arithmetic within BigInt's range, or if you want a library that silently picks a precision for you. Before committing, verify two things in your own code: that every BigNumber is constructed from a String rather than a Number literal, and that your rounding mode and decimal places are set explicitly rather than left at the defaults.
Frequently asked questions
What is bignumber.js used for?
It provides arbitrary-precision decimal and non-decimal arithmetic in JavaScript, so values that exceed the roughly 15 significant digits of the Number type, or that must not accumulate binary floating-point error, can be computed exactly. The README frames it as a replacement for the precision loss you get from numeric literals and Number arithmetic.
What is the difference between bignumber.js and big.js?
The README says big.js is less than half the size but only works with decimal numbers, has about half the methods, fewer configuration options, and does not allow NaN or Infinity. bignumber.js supports both decimal and non-decimal arithmetic and includes those values.
What is the difference between bignumber.js and decimal.js?
The README states that decimal.js adds support for non-integer powers and performs all operations to a specified number of significant digits. bignumber.js is oriented around decimal places, which is why the README recommends decimal.js as the alternative for that model.
How do I install bignumber.js?
The README's Node.js section gives the command `npm install bignumber.js`. For browsers it shows a script tag pointing at dist/bignumber.js or a minified build from jsDelivr, and for Deno it shows an import from a raw GitHub URL or unpkg.
Why does new BigNumber(0.7 + 0.1) not give 0.8?
Because the addition happens in JavaScript's Number type before the constructor is called, and the README shows the result as '0.7999999999999999'. The README recommends creating BigNumbers from String values rather than Number values to avoid this kind of precision loss.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/mikemcl-bignumber-js)