Champion-maintained polyfill for the TC39 decimal proposal
npm install proposal-decimalThis library is a prototype for the decimal proposal. There should be no
observable difference between what this library does and what the proposal
is supposed to do. If you find a mismatch between what this code does and what the
decimal proposal says it should do, please file an issue
in this repo.
This package is a prototype and is not intended for production use. (The decimal proposal is currently
at Stage 1 in the Ecma TC39 process.) Speed is important, but it is less important
than making sure we follow the spec exactly. However, if you notice that this package is significantly slower than
other decimal implementations, please file an issue.
There are a few different ways out there to model decimal numbers. The decimal proposal currently intends to use
the IEEE 754 Decimal128 decimal floating-point standard. There is one
twist, though: we do not expose the precision (or, officially, _quantum_) of Decimal128 values. A consequnce of this
decision is that we do not support trailing zeroes. Thus, the conversion from "1.2" and "1.20" to Decimal128 values
yields _distinct_ values in the official IEEE 754 Decimal128 universe, bot for the purposes of the decimal proposal,
they are the same. In effect, Decimal128 is a representation of mathematical values having up to 34 significant digits
(but without trailing zeroes) and an exponent range of -6143 to +6144. IEEE 754 Decimal128 specifies rules for how
the precision of the arguments of an operation carry over to the precision of the result. We do not expose this
information. You can think of the Decimal128 values in this package as points on the number line, or mathematical
values.
``javascript`
import { Decimal128 } from "proposal-decimal";
let a = new Decimal128("0.1");
let b = new Decimal128("0.2");
let c = a.add(b);
console.log(c.toString() === "0.3"); // true
Here are the operations that this package supports:
- absolute value (abs)negate
- negation ()add
- addition ()subtract
- subtraction ()multiply
- multiplication ()divide
- division ()remainder
- remainder ()
There is a single round method that takes a rounding mode as an argument. The rounding modes are:
- "ceil"
- "floor"
- "trunc"
- "halfEven" (the default, as with JS Numbers)
- "halfExpand"
- toString emitting both decimal and exponential syntax (like Number.prototype.toString)toFixed
- for fixed-point notation (like Number.prototype.toFixed)toPrecision
- for emitting a string with a specified number of significant digits (like Number.prototype.toPrecision)
- toNumber to convert to a JavaScript NumbertoBigInt
- to convert to a JavaScript BigInt (throws for non-integers)
Decimal128 values can be constructed from:
- a String in decimal notation (e.g., "0.1")"1e-1"
- a String in exponential notation (e.g., )"NaN"
- one of the String values , "Infinity", "-Infinity"0.1
- a Number (e.g., )42n
- a BigInt (e.g., )
- isNaN to check for NaNisFinite
- to check for a finite numberisZero
- to check for zeroisNegative
- to check for a negative number
- equality (equals) to compare for mathematical equalitynotEquals
- difference () to compare for mathematical inequalitylessThan
- less than () to compare mathematical orderlessThanOrEquals
- less than or equal to () to compare mathematical ordergreaterThan
- greater than () to compare mathematical ordergreaterThanOrEquals
- greater than or equal to () to compare mathematical ordercmp
- compare () to compare mathematical order
Why not just less-than and equals? The reason for the proliferation of all these comparisons is due to NaN and -0,lessThan
which is not 0). Thus, simply negating does not give you greaterThanOrEquals. Even if you know you'reNaN
dealing with non- values, you need to watch out for -0.
After installing this NPM package (npm install proposal-decimal), the dist subdirectory contains a single ESMDecimal128.mjs
module, . It exports a single class, Decimal128.
To use this package in Node.js, you can import the module as follows:
`javascript`
import { Decimal128 } from "proposal-decimal";
// your code goes here
// for example:
const x = new Decimal128("0.1");
const y = new Decimal128("0.2");
console.log(x.add(y).toString());
To use this package in a browser, try something like this:
`html`
This package is written in TypeScript. Unit tests are in Jest. There are other external dependencies.
The examples` subdirectory contains some example code for your inspection.
Please file an issue if you find a bug or have a
feature request.