decimal.js
本篇范围
本篇聚焦 decimal.js —— 为 JavaScript 提供任意精度的十进制(Decimal)数类型,用于规避 IEEE 754 浮点误差(0.1 + 0.2 !== 0.3)、做金额与高精度计算。它与同作者的 big.js(最精简)、bignumber.js(居中、支持多进制)属同一选型方向,本篇在取舍与对比时重点展开三者差异。版本基线 decimal.js 10.x(本地实测 10.6.0)。
decimal.js 由 Michael Mclaughlin 编写,官方定位是「An arbitrary-precision Decimal type for JavaScript」——把整数、浮点、各种进制都用任意精度的十进制表示,并复刻了大量 Number.prototype 与 Math 的方法。核心用法是 new Decimal(value) 构造、再用 plus / minus / times / dividedBy / mod / pow / sqrt 等方法运算:所有实例不可变(immutable),每个运算都返回新的 Decimal,因此天然支持链式调用,原值分毫不动。
它最被误解的一点是精度语义:配置项 precision(默认 20)指的是有效数字(significant digits)位数,不是小数位数——官方 README 明确「decimal.js 以有效数字而非小数位指定精度,并把所有计算都舍入到该精度」。默认舍入模式 rounding 为 4(ROUND_HALF_UP,四舍五入、平局远离零);可用 Decimal.set({ precision, rounding }) 全局配置,或用 Decimal.clone(config) 派生互不干扰的独立构造函数。输出端用 toFixed(定点字符串、补尾随零)、toString(去尾随零)、toNumber(回原生 number)、toDP / toSF(按小数位 / 有效数字舍入)等。它支持 NaN 与 Infinity(1/0 得 Infinity 而非抛错),并提供三角、对数、exp、非整数幂等高级数学函数——这也是它比 big.js、bignumber.js 更全、体积也最大的原因。
评价
优点
- 彻底规避浮点误差:任意精度十进制运算,
new Decimal(0.1).plus(0.2).equals(0.3)为true - 功能最全:四则之外还有
sqrt / cbrt、三角 / 反三角 / 双曲、ln / log / log2 / log10、exp、非整数pow - 不可变 + 链式:每步返回新实例,纯函数式变换,链式调用安全
- 完善的舍入控制:9 种
ROUND_*模式(含银行家舍入ROUND_HALF_EVEN),可全局或按调用指定 - 支持 NaN / Infinity 与多进制:
1/0得 Infinity 不抛错;字符串支持0x / 0o / 0b前缀 - 配置可隔离:
Decimal.clone()派生独立精度策略,避免全局状态污染 - TypeScript 友好:包内自带
.d.ts,Decimal既是构造函数也是类型,无需装@types
缺点
- 体积最大:含三角 / 对数 / exp,比 big.js、bignumber.js 都大——只做基础金额时是浪费
precision易被误解为小数位:实为有效数字,precision=5时1000/3得333.33(仅 2 位小数)- 不能用运算符:
+ - * /、===对 Decimal 对象会退回浮点 / 比较引用,必须用方法 - 提前
toNumber即前功尽弃:中途转回 number 会重新引入浮点误差 - 链式运算受
precision累积舍入:高精度场景需主动调高precision(如 40/50) - 基础场景过剩:仅需四则 + 两位小数金额时,更轻的 big.js 往往更合适