BigNum — Arbitrary Precision Integers
1.90 kB minified + gzipped
Financial ledgers, billing engines, cryptocurrency balances, and 64-bit database snowflake IDs
cannot safely use JavaScript’s standard number type. Because number is a 64-bit IEEE-754 float,
it suffers from two critical limitations:
- Floating-point precision drift: Representing currency amounts in dollars (
0.1 + 0.2) introduces binary rounding errors (0.30000000000000004), which compounds across ledger entries. - Safe integer ceiling (
Number.MAX_SAFE_INTEGER): Standard numbers lose integer precision above9,007,199,254,740,991(2^53 - 1). A 64-bit database identifier or an 18-decimal-place token balance (such as Wei in Ethereum) silently corrupts low-order digits when parsed as anumber.
JavaScript’s native bigint solves both representation limits, but its runtime ergonomics are
hazardous inside pipelines:
BigNum wraps native bigint in pure, non-throwing, data-last utilities. Every conversion and
division operation that can fail returns an explicit Maybe container instead of throwing runtime
exceptions, and every arithmetic helper is curried for direct use in pipe.
Mental Model
Section titled “Mental Model”BigNum does not wrap bigint in a custom object or class; values remain native JavaScript
bigint primitives (100n, 0n, -42n) with zero memory overhead. BigNum provides the safe
boundary converters (BigNum.from.*, BigNum.to.*), predicates (BigNum.is.*), curried
arithmetic, and collection aggregations needed to manipulate bigint values cleanly inside
functional pipelines.
Safe Parsing and Conversions
Section titled “Safe Parsing and Conversions”To parse untrusted strings — such as API query parameters, JSON string fields, or database drivers
returning 64-bit integers as text — use BigNum.from.string. It returns Some(bigint) for valid
integer strings and None for empty, whitespace-only, or malformed strings without throwing a
SyntaxError:
When converting between number and bigint, BigNum.from.number and BigNum.to.number enforce
JavaScript’s safe integer boundaries (Number.MIN_SAFE_INTEGER to Number.MAX_SAFE_INTEGER).
Passing a float, NaN, Infinity, or an integer outside the safe range returns None instead of
throwing or silently losing precision:
Numeric Predicates (BigNum.is)
Section titled “Numeric Predicates (BigNum.is)”The BigNum.is namespace provides pure predicates for filtering and branching on bigint values:
Curried Arithmetic and Safe Division
Section titled “Curried Arithmetic and Safe Division”All arithmetic functions in BigNum are curried and data-last. BigNum.add, BigNum.subtract,
BigNum.multiply, and BigNum.abs operate on bigint values directly. Note that
BigNum.subtract(amount)(from) computes from - amount:
In native JavaScript, dividing or taking the remainder of a bigint by 0n throws a runtime
RangeError: Division by zero. BigNum.divide(divisor)(dividend) and
BigNum.remainder(divisor)(dividend) catch zero divisors before evaluation and return
Maybe<bigint> (performing truncating integer division when the divisor is non-zero):
Boundaries and Clamping
Section titled “Boundaries and Clamping”To enforce minimum and maximum transaction limits or check whether an identifier falls within a
shard range, use BigNum.clamp, BigNum.between, and BigNum.inRange:
Collection Aggregations
Section titled “Collection Aggregations”BigNum.sum totals an array of bigint values (returning 0n for an empty array), while
BigNum.min and BigNum.max return Maybe<bigint> so empty arrays are handled explicitly:
Pipeline Composition
Section titled “Pipeline Composition”Here is an end-to-end financial settlement pipeline that parses raw string line items (in cents),
filters for positive charges, applies a minimum charge floor of 100n cents ($1.00), sums the
batch total, and computes an equal split across recipientCount payout accounts:
Problems it solves
Section titled “Problems it solves”- Financial ledger arithmetic without precision drift: In billing systems, payment processors,
and ecommerce platforms, calculating money using floating-point numbers produces subtle rounding
errors.
BigNumprovides exact integer arithmetic for cents, basis points, and minor currency units usingbigint. - Crypto token and subunit scaling without precision loss: Scaling crypto tokens (such as
converting between Ether and 18-decimal-place Wei, or Bitcoin and Satoshis) exceeds JavaScript’s
Number.MAX_SAFE_INTEGER.BigNumhandles arbitrarily large integers with exact precision and guardsnumberconversions viaBigNum.from.numberandBigNum.to.number. - Safe parsing of 64-bit database identifiers and snowflake IDs: Calling
BigInt()on untrusted query strings or JSON payloads throws runtime exceptions on invalid characters.BigNum.from.stringreturnsMaybe<bigint>, safely handling unvalidated input at API boundaries withouttry/catchblocks. - Crash-free division and remainder calculations: Native
bigintdivision by0nthrows a runtimeRangeError.BigNum.divideandBigNum.remainderreturnMaybe<bigint>, turning zero divisors into explicitNonevalues. - Pipelined
biginttransformations and boundary clamping: Chaining mathematical adjustments (such as calculating fee tiers, applying deductions, and clamping transaction minimums) insidepipeusing curried, data-last combinators (BigNum.add,BigNum.subtract,BigNum.multiply,BigNum.between,BigNum.inRange,BigNum.clamp).