Arbitrary-precision Decimal Arithmetic
decimal.js is an arbitrary-precision Decimal type for JavaScript, providing robust arithmetic capabilities for numbers that require exact precision, such as financial calculations. Currently at version 10.6.0, it offers a stable and actively maintained solution. Unlike bignumber.js, decimal.js defines precision in terms of significant digits rather than decimal places, aligning with Python's decimal module. It further distinguishes itself by including comprehensive trigonometric functions and support for non-integer powers, making it a more feature-rich (and larger) library than bignumber.js or big.js. The library has no external dependencies and maintains wide platform compatibility by using only ECMAScript 3 features. It ships with TypeScript declaration files, ensuring type safety for modern JavaScript projects.
Common errors
-
TypeError: Decimal is not a constructor
cause Attempting to use `Decimal` without the `new` keyword or an incorrect CommonJS import when the module's default export is the constructor.fixAlways instantiate `Decimal` with `new`, e.g., `const num = new Decimal('123.45');`. For CommonJS, ensure `const Decimal = require('decimal.js');` and not `const { Decimal } = require('decimal.js');`. -
Calculations result in unexpected floating-point inaccuracies despite using decimal.js.
cause Input numbers or intermediate steps are still being processed as native JavaScript Numbers before being converted to Decimal instances, introducing imprecision.fixConvert all numeric inputs to strings before creating Decimal instances, especially for values prone to floating-point issues (e.g., `new Decimal('0.1').plus(new Decimal('0.2'))`). Ensure all arithmetic operations are performed using Decimal methods.
Warnings
- gotcha Passing JavaScript Number literals with more than 15 significant digits or outside the safe integer range (Number.MAX_SAFE_INTEGER and Number.MIN_SAFE_INTEGER) directly to the Decimal constructor can lead to precision loss or incorrect values (e.g., 'Infinity', '0') before decimal.js even processes them, as JavaScript's native Number type cannot accurately represent these values.
- gotcha Arithmetic operations performed directly on native JavaScript Numbers (e.g., `0.1 + 0.2`) before passing them to Decimal.js can introduce floating-point inaccuracies. Decimal.js can only correct precision for operations it performs itself.
- gotcha Decimal.js uses significant digits for precision, which differs from libraries like bignumber.js that use decimal places. This means rounding occurs on all calculations, not just division.
Install
-
npm install decimal.js -
yarn add decimal.js -
pnpm add decimal.js
Imports
- Decimal
const Decimal = require('decimal.js').Decimal;import Decimal from 'decimal.js';
- Decimal
import Decimal from 'decimal.js';
const Decimal = require('decimal.js'); - Decimal
import * as Decimal from 'decimal.js';
import { Decimal } from 'decimal.js';
Quickstart
import Decimal from 'decimal.js';
// Initialize Decimal instances
const x = new Decimal(123.4567);
const y = new Decimal('123456.7e-3');
const z = new Decimal(x);
console.log(`x: ${x}`);
console.log(`y: ${y}`);
console.log(`z: ${z}`);
console.log(`x equals y: ${x.equals(y)}`); // true
console.log(`y equals z: ${y.equals(z)}`); // true
// Demonstrate precision loss with native JavaScript Number literals
console.log('\nDemonstrating native Number precision pitfalls:');
const lossyNumber = new Decimal(1.0000000000000001);
console.log(`new Decimal(1.0000000000000001): ${lossyNumber}`); // Expected '1' (due to JS Number precision)
const largeNumberLoss = new Decimal(99999999999999999999);
console.log(`new Decimal(99999999999999999999): ${largeNumberLoss}`); // Expected '100000000000000000000'
// Arithmetic precision loss
const nativeSum = 0.7 + 0.1;
const decimalSum = new Decimal(0.7).plus(new Decimal(0.1));
console.log(`0.7 + 0.1 (native): ${nativeSum}`); // 0.7999999999999999
console.log(`new Decimal(0.7).plus(new Decimal(0.1)): ${decimalSum}`); // 0.8