QuickJS already supports arbitrary-precision decimals
QuickJS is a
neat JavaScript engine by
Fabrice
Bellard. It’s fast and small (version 2021-03-27 clocks in at 759 Kb). It
includes support for arbitrary-precision decimals, even though
the TC39 decimal proposal
is (at the time of writing) still at Stage 2. You can install it using
the tool of your choice; I was able to install it using Homebrew for
macOS (the formula is called quickjs
) and FreeBSD and
OpenBSD. It can also be installed using
esvu. (It doesn’t seem to be available as a package on Ubuntu.) To get
started with arbitrary precision decimals, you need to fire up
QuickJS with the bignum
flag:
$ qjs --bignum
QuickJS - Type "\h" for help
qjs > 0.1 + 0.2 === 0.3
false
qjs > 0.1m + 0.2m === 0.3m
true
qjs > 0.12345678910111213141516171819m * 0.19181716151413121110987654321m
0.0236811308550240594910066199325923006903586430678413779899m
(The m
is the proposed suffix for literal high-precision
decimal numbers that proposal-decimal is supposed to give us.)
Notice how we nicely
unbreak
JavaScript decimal arithmetic, without having to load a library. The
final API in the official TC39 Decimal proposal still has not been
worked out. Indeed, a core question there remains outstanding at the
time of writing: what kind of numeric precision should be supported?
(The two main contenders are arbitrary precision and the other being
128-bit IEEE 754 (high, but not *arbitrary*, precision). QuickJS does
arbitrary precision.) Nonetheless, QuickJS provides a
BigDecimal
function:
qjs > BigDecimal("123456789.0123456789")
123456789.0123456789m
Moreover, you can do basic arithmetic with decimals: addition,
subtraction, multiplication, division, modulo, square roots, and
rounding. Everything is done with infinite precision (no loss of
information). If you know, in advance, what precision is needed, you
can tweak the arithmetical operations by passing in an options
argument. Here’s an example of adding two big decimal numbers:
qjs > var a = 0.12345678910111213141516171819m;
undefined
qjs > var b = 0.19181716151413121110987654321m;
undefined
qjs > BigDecimal.add(a,b)
0.3152739506152433425250382614m
qjs > BigDecimal.add(a,b, { "roundingMode": "up", "maximumFractionDigits": 10 })
0.3152739507m
Jesse
Alama