@isopodlabs/big
v0.2.0
Published
High precision arithmetic.
Maintainers
Readme
@isopodlabs/big
This module provides high-precision arithmetic and transcendental functions for big integers and custom floating-point numbers. It is designed for numerical applications requiring more precision than JavaScript's native number type.
In addition, the 'dec' submodule provides (almost) the same functionality, but using a decimal exponent.
☕ Support My Work
If you use this package, consider buying me a cup of tea to support future updates!
Features
- Arbitrary-precision integer math (
bigint) - Custom
floatclass for high-precision floating-point arithmetic using binary exponents - Custom
dec.floatclass for high-precision floating-point arithmetic using decimal exponents - Arithmetic methods add, sub, mul, div, mod, divmod
- Comparison methods eq, ne, lt le, gt, ge
- IEEE-754 compatible rounding modes
- High-precision implementations of:
- Square root, n-th root
- Trigonometric functions: sin, cos, tan, asin, acos, atan
- Exponential and logarithmic functions: exp, ln
- Random number generation with specified bit width
- Pi calculation using the Gauss-Legendre algorithm
- Utility functions for max, min, shifting, and comparison
Usage
Import the module:
import * as big from '@isopodlabs/big';Creating Floats
const a = big.float.from(123.456); // From number
const b = big.float.from('3.14159'); // From string
const c = big.float.from(12345678901234567890n); // From bigintArithmetic
const sum = a.add(b);
const product = a.mul(b);
const quotient = a.div(b);Transcendental Functions
const s = big.sin(a, bits); // Sine
const c = big.cos(a, bits); // Cosine
const t = big.tan(a, bits); // Tangent
const l = big.log(a, bits); // Natural logarithm
const e = big.exp(a, bits); // ExponentialRandom Number Generation
const r = big.random(bits); // Random float with specified bits of precisionPi Calculation
const pi = big.pi(bits); // High-precision piAPI Reference
bigint functions
These are used by the float classes internally, but are exposed for direct roots of bigints.
sqrt(x: bigint)- Square rootroot(x: bigint, b: number)— n-th root
Rounding Modes
These can be passed to precision modifying functions and toInt.
Round.trunc: Truncate toward zeroRound.down: Round toward −∞Round.up: Round toward +∞Round.halfUp: Round to nearest, ties away from zeroRound.halfEven: Round to nearest, ties to even (default IEEE-754)
float class methods
Construction
float.from(value: number | bigint | string | float): float— Create a float from various types.float.fromString(str: string, bits: number): float— Parse a string to float with specified precision.
Arithmetic
add(other: float | number | bigint): float— Additionsub(other: float | number | bigint): float— Subtractionmul(other: float | number | bigint): float— Multiplicationdiv(other: float | number | bigint): float— Divisionmod(other: float | number | bigint): float— Modulusdivmod(other: float | number | bigint): [bigint, float]— Whole part of division and remaindersquare(): float— Squaresqrt(): float— Square rootpow(exp: number): float— Powerroot(base: number): float— n-th root
Precision and Shifting
addPrecision(bits: number, mode = Round.halfEven): float— Increase precisionsetPrecision(bits: number, mode = Round.halfEven): float— Set precisioncapPrecision(bits: number, mode = Round.halfEven): float— Cap precisionshift(bits: number): float— multiply by powers of 2
Rounding and Integer Conversion
toInt(mode = Round.trunc): bigint— Convert to integerfrac(): float— Fractional partfloor(): float— Round downceil(): float— Round uptrunc(): float— Truncate toward zeroround(): float— Round to nearest
Comparison
compare(other: float | number | bigint): number— Compare valueslt0(): boolean— Less than zerole(other: float | number | bigint): boolean— Less than or equaleq(other: float | number | bigint): boolean— Equalne(other: float | number | bigint): boolean— Not equalge(other: float | number | bigint): boolean— Greater than or equallt(other: float | number | bigint): boolean— Less thangt(other: float | number | bigint): boolean— Greater than
Utility
neg(): float— Negateabs(): float— Absolute valuetoString(base?: number, max_digits?: number): string— String representation
Static Properties
float.zero— 0float.one— 1float.two— 2float.Infinity— Infinity
functions
max(...values: float[]): float- Maximum of all valuesmin(...values: float[]): float- Minimum of all valuesrandom(bits: number): float- Random number with given number of bits (use Math.random internally)pi(bits: number): float- Pi to the given number of binary places
These correspond to the Math functions, but compute results to bits binary places.
sin(x: float | number | bigint, bits: number): floatcos(x: float | number | bigint, bits: number): floattan(x: float | number | bigint, bits: number): floatasin(x: float | number | bigint, bits: number): floatacos(x: float | number | bigint, bits: number): floatatan(x: float | number | bigint, bits: number): floatlog(x: float | number | bigint, nbits: number): floatexp(x: float | number | bigint, bits: number): float
On Precision
float.from(string) returns a float with the minimum precision required to hold the number of digits provided. Fractional values that do not have exact binary representations may not have the accuracy you expect. Use float.fromString to supply the precision at time of parsing.
eg.
const a = big.float.from('0.1');
console.log(a.toString()); // outputs '0.1' - huzzah
console.log(a.addPrecision(100).toString()); // outputs '0.0625' - wtf?
const b = big.float.fromString('0.1', 100);
console.log(b.toString());
console.log(b.addPrecision(100).toString()); // still outputs '0.1'
console.log(b.addPrecision(100).toString(10, Infinity)); // outputs 0.0999999999999999999999999999999704177160542120572970601788019 (only ~30 valid digits)
add/sub/mod/divmodreturn floats with the higher precision ofthisandothermulreturns a float with the precision ofthisplus the precision ofotherdivreturns a float with the precision ofthissqrtreturns a float with half the precision ofthispowreturns a float with n times the precision ofthisrootreturns a float with the precision ofthisdivided bybasefrac/floor/ceil/trunc/roundreturn floats with the same precision asthis
To compute a result to a higher precision, increase the precision of the this (or other) before calling a method.
To reduce the precision of a result, use capPrecision or setPrecision on it.
e.g.
const sqrt2 = big.float.from(2).setPrecision(2000).sqrt(); // Calculate sqrt2 to 1000 binary places
const ab = a.mul(b).capPrecision(100); // cap the precision to 100 binary placesDecimal Floating Point (dec.float)
The dec.float class provides high-precision decimal floating-point arithmetic, similar to big.float but with a base-10 exponent instead of base-2. This means numbers are represented as $m \times 10^e$ (mantissa times a power of ten), making it ideal for financial and scientific calculations where decimal accuracy is required.
Key Features
- Decimal exponent: Values are stored as $m \times 10^e$ (mantissa and decimal exponent)
- Consistent decimal rounding: Supports all standard rounding modes, including half-even ("bankers' rounding")
- API parity with
big.float: Most methods and usage patterns are the same asbig.float
Example Usage
import { dec } from '@isopodlabs/big';
// Create decimal floats
const a = dec.float.from('123.456'); // From string
const b = dec.float.from(0.1); // From number
// Arithmetic
const sum = a.add(b);
const product = a.mul(b);
On Precision
The precision in dec.float refers to the number of decimal digits in the mantissa. This is different from big.float, where precision is measured in binary bits.
Most of the 'On Precision' section about big.float still applies, except that there is no seperate fromString because the string conversion is exact.
When to Use
- Use
big.floatfor binary floating-point math (base-2 exponent, scientific computing) - Use
dec.floatfor decimal math (base-10 exponent, financial, accounting, or any case where decimal rounding is critical)
License
MIT
