big.js vs bignumber.js vs decimal.js vs mathjs
JavaScript 高精度数值计算库选型指南
big.jsbignumber.jsdecimal.jsmathjs类似的npm包:

JavaScript 高精度数值计算库选型指南

JavaScript 原生的 Number 类型基于 IEEE 754 标准,导致浮点数运算存在精度丢失问题(例如 0.1 + 0.2 !== 0.3)。big.jsbignumber.jsdecimal.jsmathjs 都是为了解决这一问题而设计的库,但它们的侧重点不同。前三个专注于提供任意精度的十进制算术运算,适合金融、会计等对精度敏感的场景;而 mathjs 是一个功能全面的数学计算引擎,不仅支持高精度数字,还提供矩阵、代数、统计等复杂数学功能。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
big.js05,19658.9 kB81 年前MIT
bignumber.js07,008500 kB82 个月前MIT
decimal.js07,252284 kB221 年前MIT
mathjs015,0729.43 MB2095 个月前Apache-2.0

JavaScript 高精度数值计算库深度对比:big.js vs bignumber.js vs decimal.js vs mathjs

在 JavaScript 中,0.1 + 0.2 !== 0.3 是一个经典问题。这是因为 JS 的 Number 类型基于 IEEE 754 双精度浮点数标准,无法精确表示某些十进制小数。为了解决这个问题,社区涌现了多个高精度计算库。本文将深入对比 big.jsbignumber.jsdecimal.jsmathjs,帮助你在架构设计中做出正确选择。

🏗️ 核心设计理念:类实例 vs 函数工具

这四个库在 API 设计风格上有显著差异。前三个库(big.jsbignumber.jsdecimal.js)主要采用面向对象的设计,通过实例方法链式调用;而 mathjs 则是一个函数式的数学引擎,提供全局工具函数。

big.js 采用极简的类设计,实例化后直接调用方法。

import Big from 'big.js';
const x = new Big(0.1);
const y = new Big(0.2);
const result = x.plus(y); // 返回 Big 实例
console.log(result.toString()); // "0.3"

bignumber.js 同样基于类,但支持更丰富的链式操作和配置。

import BigNumber from 'bignumber.js';
const x = new BigNumber(0.1);
const y = new BigNumber(0.2);
const result = x.plus(y); // 返回 BigNumber 实例
console.log(result.toString()); // "0.3"

decimal.js 的 API 设计与 bignumber.js 非常相似,但在方法命名上略有不同(如 add 而非 plus)。

import Decimal from 'decimal.js';
const x = new Decimal(0.1);
const y = new Decimal(0.2);
const result = x.add(y); // 返回 Decimal 实例
console.log(result.toString()); // "0.3"

mathjs 提供全局命名空间,既可以处理普通数字,也可以配置为处理大数。

import * as math from 'mathjs';
// 默认可能使用普通数字,需显式使用 bignumber 类型或配置
const result = math.add(math.bignumber(0.1), math.bignumber(0.2));
console.log(result.toString()); // "0.3"

⚙️ 精度配置与舍入模式

在金融场景中,舍入模式(如四舍五入、向下取整)至关重要。不同库对配置的管理方式不同。

big.js 通过静态属性配置,全局生效,配置项较少。

import Big from 'big.js';
Big.RM = 1; // 设置舍入模式:向下取整
Big.DP = 2; // 设置小数位数
const result = new Big(1.555).div(1); // 1.55

bignumber.js 提供 config 方法,支持更细粒度的控制,包括指数范围。

import BigNumber from 'bignumber.js';
BigNumber.config({ DECIMAL_PLACES: 2, ROUNDING_MODE: 1 });
const result = new BigNumber(1.555).dividedBy(1); // 1.55

decimal.js 同样使用 config,但在处理极大或极小数值时的行为更加一致。

import Decimal from 'decimal.js';
Decimal.set({ precision: 20, rounding: 1 });
const result = new Decimal(1.555).div(1); // 1.55

mathjs 的配置更为复杂,因为它需要协调整个数学引擎的行为。

import * as math from 'mathjs';
math.config({ precision: 20, number: 'BigNumber' });
const result = math.divide(1.555, 1); // 依赖全局配置

🧮 功能范围:基础算术 vs 全面数学

这是选择 mathjs 与其他三个库的分水岭。如果你只需要加减乘除,前三个库更轻量;如果你需要三角函数、矩阵或表达式解析,mathjs 是唯一选择。

big.js 仅支持基础算术(加减乘除、开方、比较)。

// 不支持三角函数,会报错或无此方法
// new Big(1).sin() // undefined

bignumber.js 支持基础算术和部分高级运算(如幂、绝对值),但不支持三角函数。

const x = new BigNumber(2);
const pow = x.exponentiatedBy(3); // 8
// 不支持 sin, cos 等

decimal.jsbignumber.js 基础上扩展了更多数学方法,包括三角函数和对数。

const x = new Decimal(1);
const sinVal = x.sin(); // 支持三角函数
const logVal = x.ln();   // 支持对数

mathjs 提供完整的数学标准库支持,包括矩阵、复数、单位转换等。

const matrix = math.matrix([[1, 2], [3, 4]]);
const det = math.det(matrix); // 计算行列式
const expr = math.evaluate('1.1 + 0.2'); // 解析字符串表达式

📦 工程化考量与维护状态

在大型项目中,库的维护状态和类型支持(TypeScript)是关键决策因素。

  • big.js:维护稳定,更新频率低,因为功能已冻结。类型定义完善。体积最小。
  • bignumber.js:非常活跃,社区生态最好,几乎所有高精度场景的首选。类型定义完善。
  • decimal.js:活跃维护,与 bignumber.js 同作者。类型定义完善。
  • mathjs:非常活跃,功能迭代快。体积较大,类型定义完善但配置复杂。

📊 总结对比表

特性big.jsbignumber.jsdecimal.jsmathjs
核心定位极简十进制计算通用高精度计算增强十进制计算全能数学引擎
API 风格类实例 (.plus)类实例 (.plus)类实例 (.add)函数式 (math.add)
三角函数❌ 不支持❌ 不支持✅ 支持✅ 支持
表达式解析❌ 不支持❌ 不支持❌ 不支持✅ 支持 (evaluate)
配置复杂度
典型场景货币计算通用高精度科学十进制工程/科学计算

💡 架构师建议

big.js 就像一把精致的小刀 🔪 —— 专注、锋利、无多余功能。如果你的需求仅仅是解决金额计算精度问题,且对包体积敏感,它是最佳选择。

bignumber.js 就像一把瑞士军刀 🇨🇭 —— 功能均衡,可靠性高。如果你不确定未来需求是否会扩展,或者需要处理加密货币等非传统货币单位,选它最稳妥。

decimal.js 就像一把专业手术刀 🏥 —— 在十进制领域比 bignumber.js 更严谨。如果你在进行严格的财务审计或科学记录,且需要三角函数支持,它比 bignumber.js 更合适。

mathjs 就像一个完整的工作台 🛠️ —— 功能强大但笨重。只有当你需要解析用户输入的数学公式、处理矩阵或进行复杂单位转换时,才值得引入它。

最终建议:对于 90% 的前端业务场景(电商、金融后台),bignumber.js 是综合性价比最高的选择。若追求极致轻量选 big.js,若涉及复杂数学运算选 mathjs

如何选择: big.js vs bignumber.js vs decimal.js vs mathjs

  • big.js:

    选择 big.js 如果你的项目对包体积非常敏感,且只需要基础的加减乘除运算。它设计极简,没有多余的配置,非常适合前端金融表单计算或货币处理,但在处理极大数值或非十进制运算时能力有限。

  • bignumber.js:

    选择 bignumber.js 如果你需要一个社区认可度高、文档完善且功能平衡的库。它支持任意精度的十进制和非十进制运算,配置灵活,是大多数通用高精度计算场景(如加密货币、科学计算)的安全选择。

  • decimal.js:

    选择 decimal.js 如果你需要更严格的十进制语义和更丰富的数学方法(如平方根、三角函数)。它与 bignumber.js 出自同一作者,但在处理纯十进制逻辑时往往表现更一致,适合对数值语义要求严格的系统。

  • mathjs:

    选择 mathjs 如果你的需求不仅仅是高精度加减乘除,而是需要解析数学表达式、处理矩阵运算或进行复杂的科学计算。它的功能最强大,但体积也最大,适合构建计算器应用或工程类工具。

big.js的README

big.js

A small, fast JavaScript library for arbitrary-precision decimal arithmetic.

npm version npm downloads CI

Features

  • Simple API
  • Faster, smaller and easier-to-use than JavaScript versions of Java's BigDecimal
  • Only 6 KB minified
  • Replicates the toExponential, toFixed and toPrecision methods of JavaScript Numbers
  • Stores values in an accessible decimal floating point format
  • Comprehensive documentation and test set
  • No dependencies
  • Uses ECMAScript 3 only, so works in all browsers

The little sister to bignumber.js and decimal.js. See here for some notes on the difference between them.

Install

The library is the single JavaScript file big.js or the ES module big.mjs.

Browsers

Add Big to global scope:

<script src='path/to/big.js'></script>

ES module:

<script type='module'>
import Big from './path/to/big.mjs';

Get a minified version from a CDN:

<script src='https://cdn.jsdelivr.net/npm/big.js@7.0.1/big.min.js'></script>

Node.js

$ npm install big.js

CommonJS:

const Big = require('big.js');

ES module:

import Big from 'big.js';

Deno

import Big from 'https://raw.githubusercontent.com/mikemcl/big.js/v7.0.1/big.mjs';
import Big from 'https://unpkg.com/big.js@latest/big.mjs';

Use

In the code examples below, semicolons and toString calls are not shown.

The library exports a single constructor function, Big.

A Big number is created from a primitive number, string, or other Big number.

x = new Big(123.4567)
y = Big('123456.7e-3')                 // 'new' is optional
z = new Big(x)
x.eq(y) && x.eq(z) && y.eq(z)          // true

In Big strict mode, creating a Big number from a primitive number is disallowed.

Big.strict = true
x = new Big(1)                         // TypeError: [big.js] Invalid number
y = new Big('1.0000000000000001')
y.toNumber()                           // Error: [big.js] Imprecise conversion

A Big number is immutable in the sense that it is not changed by its methods.

0.3 - 0.1                              // 0.19999999999999998
x = new Big(0.3)
x.minus(0.1)                           // "0.2"
x                                      // "0.3"

The methods that return a Big number can be chained.

x.div(y).plus(z).times(9).minus('1.234567801234567e+8').plus(976.54321).div('2598.11772')
x.sqrt().div(y).pow(3).gt(y.mod(z))    // true

Like JavaScript's Number type, there are toExponential, toFixed and toPrecision methods.

x = new Big(255.5)
x.toExponential(5)                     // "2.55500e+2"
x.toFixed(5)                           // "255.50000"
x.toPrecision(5)                       // "255.50"

The arithmetic methods always return the exact result except div, sqrt and pow (with negative exponent), as these methods involve division.

The maximum number of decimal places and the rounding mode used to round the results of these methods is determined by the value of the DP and RM properties of the Big number constructor.

Big.DP = 10
Big.RM = Big.roundHalfUp

x = new Big(2);
y = new Big(3);
z = x.div(y)                           // "0.6666666667"
z.sqrt()                               // "0.8164965809"
z.pow(-3)                              // "3.3749999995"
z.times(z)                             // "0.44444444448888888889"
z.times(z).round(10)                   // "0.4444444445"

The value of a Big number is stored in a decimal floating point format in terms of a coefficient, exponent and sign.

x = new Big(-123.456);
x.c                                    // [1,2,3,4,5,6]    coefficient (i.e. significand)
x.e                                    // 2                exponent
x.s                                    // -1               sign

For advanced usage, multiple Big number constructors can be created, each with an independent configuration.

For further information see the API reference documentation.

Minify

To minify using, for example, npm and terser

$ npm install -g terser
$ terser big.js -c -m -o big.min.js

Test

The test directory contains the test scripts for each Big number method.

The tests can be run with Node.js or a browser.

Run all the tests:

$ npm test

Test a single method:

$ node test/toFixed

For the browser, see runner.html and test.html in the test/browser directory.

big-vs-number.html is a old application that enables some of the methods of big.js to be compared with those of JavaScript's Number type.

TypeScript

The DefinitelyTyped project has a Typescript type definitions file for big.js.

$ npm install --save-dev @types/big.js

Any questions about the TypeScript type definitions file should be addressed to the DefinitelyTyped project.

Licence

MIT

Contributors

Financial supporters

Thank you to all who have supported this project via Open Collective, particularly Coinbase.