BN.js: Arbitrary-Precision Big Numbers
bn.js is a fundamental pure JavaScript library providing a comprehensive implementation for arbitrary-precision integers, commonly referred to as "Big Numbers." It is currently at version 5.2.3 and maintains an active release cadence, frequently addressing bug fixes and minor improvements, as seen in recent updates like v5.2.1 and v5.2.0. A key design principle is its focus on integer arithmetic; it explicitly does not support decimal numbers, which is an important consideration for users. Differentiating features include support for in-place operations (e.g., `iadd`), unsigned operations (e.g., `umod`), and operations that take native JavaScript numbers as arguments (e.g., `addn`), allowing for performance optimizations and flexible usage patterns. It provides a wide array of utilities, arithmetic, and bitwise operations crucial for cryptographic applications, large financial calculations, and other domains requiring precision beyond standard JavaScript `Number` limits.
Common errors
-
Error: not that many bits (or similar for invalid input)
cause Attempting to initialize a BN instance with a string containing non-integer parts (e.g., decimals) or characters invalid for the specified base, especially after v5.0.0's stricter validation.fixEnsure all string inputs to the `BN` constructor are pure integer representations matching the provided base (e.g., `new BN('10', 10)` is valid, `new BN('10.5', 10)` is not). -
TypeError: BN.modn is not a function
cause Attempting to use the `.modn()` method, which was deprecated and removed in `v5.0.0`.fixReplace `bnInstance.modn(num)` with `bnInstance.mod(new BN(num))` or, for unsigned results, `bnInstance.umod(new BN(num))`. Alternatively, if `num` is a small JavaScript number, use `bnInstance.mod(new BN(num))` or `bnInstance.modn` alternatives for specific contexts if available in newer versions (refer to documentation). -
RangeError: Number can only safely store up to 53 bits (or incorrect numerical output from toNumber())
cause Calling `.toNumber()` on a BN instance that holds an integer value greater than `Number.MAX_SAFE_INTEGER` (2^53 - 1), leading to precision loss or an incorrect result.fixFor values larger than `Number.MAX_SAFE_INTEGER`, use `.toString(10)` to get the full decimal string representation. Other conversion methods like `.toArray()` or `.toBuffer()` can provide byte-level access without numeric precision limits. -
RangeError: n must be less than 0x4000000
cause A JavaScript `Number` argument passed to an `n`-suffixed method (e.g., `iaddn`, `muln`) exceeds the maximum allowed value of `0x4000000` (67,108,864).fixFor number arguments greater than `0x4000000`, convert the JavaScript `Number` into a `BN` instance first (e.g., `new BN(largeNum)`) and then use the corresponding method without the `n` suffix (e.g., `bnInstance.iadd(new BN(largeNum))`).
Warnings
- breaking Since `v5.0.0`, the BN constructor enforces stricter input validation, specifically rejecting decimal numbers when passed as a string. It expects pure integer strings matching the specified base.
- deprecated The `.modn()` method was deprecated in `v5.0.0` and should no longer be used.
- gotcha BN.js is designed exclusively for integer arithmetic. It does not support decimal numbers or floating-point operations anywhere in the library.
- gotcha The `.toNumber()` method can only safely convert `BN` instances to JavaScript `Number` primitives if their value fits within 53 bits (equivalent to `Number.MAX_SAFE_INTEGER`). Larger values will lose precision or result in incorrect numbers.
- gotcha There were interoperability issues when mixing `bn.js` v4 and v5 instances, leading to potential unexpected behavior in shared codebases.
- gotcha Versions prior to `v5.2.1` contained a serious bug in the `.toString(16)` method, potentially producing incorrect hexadecimal string representations.
- gotcha Methods with the `n` postfix (e.g., `iaddn`, `muln`) which accept a plain JavaScript `Number` argument, have an upper limit of `0x4000000` (67,108,864) for that argument. Providing a larger number will throw a `RangeError`.
Install
-
npm install bn.js -
yarn add bn.js -
pnpm add bn.js
Imports
- BN
import BN from 'bn.js';
const BN = require('bn.js'); - BN.isBN
import { isBN } from 'bn.js';const BN = require('bn.js'); const isBN = BN.isBN; - Red
const BN = require('bn.js'); const Red = BN.red('k256');
Quickstart
const BN = require('bn.js');
// Initialize Big Numbers from various bases
const hexValue = new BN('DEADBEEF', 16);
const binValue = new BN('10101010101010101010', 2);
// Decimal numbers can be large strings, exceeding standard JS Number limits
const decValue = new BN('123456789012345678901234567890');
console.log('Initialized from Hex:', hexValue.toString(16));
console.log('Initialized from Binary:', binValue.toString(2));
console.log('Initialized from large Decimal String:', decValue.toString(10));
// Perform arithmetic operations
let sum = hexValue.add(binValue);
console.log('\nSum (hexValue + binValue) in decimal:', sum.toString(10));
let product = decValue.mul(new BN(2)); // Multiply by another BN instance
console.log('Product (decValue * 2):', product.toString(10));
// Demonstrate in-place operation: `a.iadd(b)` modifies `a`
let a = new BN('100', 10);
let b = new BN('50', 10);
a.iadd(b);
console.log('In-place addition (a.iadd(b)), "a" is now:', a.toString(10)); // Should be 150
// Demonstrate unsigned modulo with negative numbers
let negative = new BN('-10');
let modulo = new BN('3');
console.log('Signed modulo (-10 mod 3):', negative.mod(modulo).toString(10)); // Expected: -1
console.log('Unsigned modulo (-10 umod 3):', negative.umod(modulo).toString(10)); // Expected: 2 ((-10 % 3) + 3)
// Convert to different formats (e.g., Buffer, Array)
// Requires Node.js Buffer to be available in the environment for toBuffer
try {
const buffer = hexValue.toBuffer('be', 4); // Big-endian, 4 bytes padded
console.log('Buffer representation of hexValue (hex string):', buffer.toString('hex'));
} catch (e) {
console.log('Buffer operations skipped (Buffer class might not be available in this environment).');
}
// Check if an object is a BN.js instance
console.log('\nIs hexValue a BN instance?', BN.isBN(hexValue));
console.log('Is a plain number a BN instance?', BN.isBN(123));