High-precision numbers for infinite scales.
DNum is a TypeScript library designed to handle values that exceed the limits of Number.MAX_VALUE without sacrificing micro-precision. By utilizing a dimensional hypercube model V = sd, DNum efficiently processes scales ranging from subatomic nanometers to intergalactic distances.
- Infinite Scaling: Represent numbers far beyond 10308 and even 101,000,000.
- Tracer System: Prevents precision loss (underflow) by collecting micro-amounts in separate buckets until they become significant.
- Banking-Safe Fast-Path: Computes values up to 1015 bit-identically with standard 64-bit floats for maximum performance.
- Scientific Functions: Native support for
sqrt(),pow(n),add(),sub(),mul(), anddiv(). - DNum Style Formatting: Unique visual representation using subscripts for dimensions and superscripts for precision.
- Lossless Persistence: Full serialization including all internal tracer data.
npm install @sayore/dnum
# or
pnpm add @sayore/dnumInstead of a massive mantissa, DNum represents values as the volume of an n-dimensional hypercube: V = sd
- s (Side length): Normalized typically within the [1.1, 100] range.
- d (Dimension): The scaling tier of the number.
When adding 1020 and 10-5, a standard 64-bit float would simply discard the smaller number. DNum parks these "micro-informations" in a TracerSystem. Once the sum of these small amounts becomes relevant (or collapse() is called), they are fused into the main value.
import { DNum } from '@sayore/dnum';
const a = DNum.fromAny(1e20);
const b = DNum.fromAny(5e18);
a.add(b);
console.log(a.toScientific()); // "1.0500e+20"DNum excels where hardware floats fail, such as correcting nanometers on a 300 billion km journey.
const distance = DNum.fromAny(300_000_000_000); // 300 billion meters
const correction = DNum.fromAny(0.000000001); // 1 nanometer
for (let i = 0; i < 100000; i++) {
distance.add(correction);
}
// collapse() merges tracers into the float, but toPreciseString()
// stitches the tracer data textually for 100% display accuracy.
console.log(distance.toPreciseString(10)); // "300000000000.0001000000"For games and simulations, DNum offers a compact, typographic representation:
- Subscripts (Bottom): The Dimension (d).
- Superscripts (Top): The Decimal precision of the side length (s).
Example Output: ₁₂12⁵⁰
const powerLevel = new DNum(12.50, 12);
console.log(powerLevel.toString(2));
// Output: ₁₂12⁵⁰
const powerLevel = new DNum(150.50, 12);
console.log(powerLevel.toString(2));
// Output: ₁₄73⁵³ (₁₂150⁵⁰ but normalized to be within 0 - 100)| Method | Description |
|---|---|
add(other) |
Adds another DNum (including tracer data). |
mul(other) |
Multiplies and scales all internal buckets. |
sqrt() |
Calculates the square root in log-space. |
pow(n) |
Raises the number to the power of n. |
collapse() |
Force-merges tracer content into the main value (hardware-level). |
toPreciseString(p) |
Outputs exact value bypassing 64-bit rounding errors. |
DNum is a powerhouse for scaling, but it is not a magic bullet:
-
The "15-Digit Window": DNum is not an Arbitrary Precision library. It uses a "moving window" of ~15 significant digits. You cannot see a grain of sand and a mountain (
$10^{20}$ scale difference) perfectly at the same time in one float. -
Dimensional Sensitivity: At very high dimensions (d > 100), the side length
$s$ becomes extremely sensitive. A tiny rounding error in$s$ can translate to a massive absolute error. -
Performance: It is slower than native
numberprimitives due to the Map-based tracer management. Use it where scale matters, not for high-frequency vertex math.
// Save including all micro-tracer data
const json = playerMoney.serialize();
// Restore perfectly
const loaded = DNum.deserialize(json);MIT - Created for infinity and beyond.