numeral vs format-number vs accounting-js vs d3-format vs mathjs vs sprintf-js
JavaScript 数字与货币格式化方案深度对比
numeralformat-numberaccounting-jsd3-formatmathjssprintf-js类似的npm包:

JavaScript 数字与货币格式化方案深度对比

这些库旨在将原始数值转换为人类可读的字符串格式,涵盖货币符号、千位分隔符、百分比及科学计数法等场景。d3-format 和 mathjs 是目前维护活跃的主流选择,分别侧重于数据可视化精度和复杂数学运算后的格式化。accounting-js 和 numeral 属于早期经典库,但目前已停止维护。sprintf-js 侧重于 C 风格字符串插值,而 format-number 则提供轻量级的基础格式支持。

npm下载趋势

3 年

GitHub Stars 排名

统计详情

npm包名称
下载量
Stars
大小
Issues
发布时间
License
numeral1,357,7779,697-34410 年前MIT
format-number42,96150-69 年前BSD-3-Clause
accounting-js19,83411946.9 kB121 年前MIT
d3-format064342.3 kB179 个月前ISC
mathjs015,0919.43 MB2356 个月前Apache-2.0
sprintf-js02,14439.9 kB723 年前BSD-3-Clause

JavaScript 数字格式化库:架构选型与实战对比

在前端开发中,将原始数值转换为用户友好的格式(如货币、百分比、千位分隔)是常见需求。虽然现代浏览器提供了原生 Intl.NumberFormat API,但在处理复杂场景、旧浏览器兼容或特定生态系统(如 D3)时,第三方库仍有其价值。本文将深度对比 accounting-js、d3-format、format-number、mathjs、numeral 和 sprintf-js,帮助你做出架构决策。

⚠️ 维护状态与生命周期:首要考量

在选择库之前,必须了解其维护状态。使用已停止维护的库会引入安全风险和技术债务。

numeral 和 accounting-js 属于早期经典库,但目前已进入停止维护状态。

  • numeral 最后更新停留在数年前,社区已普遍建议迁移。
  • accounting-js 功能单一,多年无版本迭代。

d3-format 和 mathjs 是活跃维护的库。

  • d3-format 作为 D3 生态的一部分,更新频繁,稳定性高。
  • mathjs 持续更新,适合科学计算场景。

sprintf-js 和 format-number 处于稳定期。

  • 功能成熟,变更较少,适合特定用途。

💡 建议:除非维护旧系统,否则避免在新项目中使用 numeral 和 accounting-js。

💰 货币格式化实战:语法与灵活性

货币格式化是最常见的需求,涉及符号、千位分隔和小数位数。

accounting-js 提供专用的货币函数,API 非常直观。

import accounting from 'accounting-js';

// 格式化为货币
const money = accounting.formatMoney(1234567.89, '$', 2);
// 输出:$1,234,567.89

d3-format 使用格式说明符字符串,灵活性极高。

import { format } from 'd3-format';

// 定义格式:美元,千位分隔,2 位小数
const usd = format('$,.2f');
const money = usd(1234567.89);
// 输出:$1,234,567.89

numeral 使用链式调用和模板字符串(已弃用,仅作对比)。

import numeral from 'numeral';

// 链式格式化
const money = numeral(1234567.89).format('$0,0.00');
// 输出:$1,234,567.89

mathjs 主要通过配置对象控制精度,货币符号需手动处理。

import { format } from 'mathjs';

// 控制精度,符号需自行拼接
const num = format(1234567.89, { precision: 2 });
const money = '$' + num.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
// 输出:$1,234,567.89 (需额外处理千位符)

sprintf-js 使用 C 风格占位符,不直接支持货币符号。

import sprintf from 'sprintf-js';

// 仅处理数字结构,符号需手动添加
const num = sprintf('%0,.2f', 1234567.89);
const money = '$' + num;
// 输出:$1,234,567.89

format-number 提供简单的选项对象配置。

import formatNumber from 'format-number';

// 通过配置对象控制
const formatter = formatNumber({ style: 'currency', currency: 'USD' });
const money = formatter(1234567.89);
// 输出:$1,234,567.89 (依赖底层实现)

🎯 精度控制与舍入行为

不同库对小数舍入的处理方式不同,这在金融场景中至关重要。

d3-format 支持多种舍入类型(如向上、向下、最近)。

import { formatRound } from 'd3-format';

// 强制四舍五入
const round = formatRound('.2f');
console.log(round(1.235)); // 1.24

mathjs 允许指定有效数字位数,适合科学计算。

import { format } from 'mathjs';

// 指定有效数字精度
console.log(format(12345, { precision: 3 })); // 1.23e+4

numeral 默认四舍五入,但配置项有限。

import numeral from 'numeral';

console.log(numeral(1.235).format('0.00')); // 1.24

accounting-js 默认四舍五入,可配置精度。

import accounting from 'accounting-js';

console.log(accounting.formatMoney(1.235, '', 2)); // 1.24

sprintf-js 遵循标准 C 库舍入规则。

import sprintf from 'sprintf-js';

console.log(sprintf('%.2f', 1.235)); // 1.24

format-number 通常封装了原生行为,配置较简单。

import formatNumber from 'format-number';

const formatter = formatNumber({ round: 2 });
console.log(formatter(1.235)); // 1.24

🧩 通用性与生态系统集成

除了数字格式化,库的通用性和与其他工具的集成能力也是考量点。

d3-format 是数据可视化领域的标准。

  • 与 d3-scale、d3-axis 无缝配合。
  • 适合图表标签、坐标轴格式化。

mathjs 是数学计算的全能工具。

  • 支持表达式解析、矩阵、复数。
  • 格式化只是其众多功能之一。

sprintf-js 专注于字符串插值。

  • 适合日志输出、动态消息生成。
  • 不局限于数字,可格式化日期、对象。

numeral / accounting-js / format-number 专注于数字。

  • 功能单一,集成成本低,但扩展性弱。

📊 总结对比表

特性d3-formatmathjssprintf-jsnumeralaccounting-jsformat-number
维护状态✅ 活跃✅ 活跃✅ 稳定❌ 停止维护❌ 停止维护⚠️ 低频
主要用途数据可视化科学计算字符串插值通用格式化货币格式化轻量格式化
API 风格格式说明符配置对象C 风格占位符链式调用专用函数配置对象
包体积小大极小中小极小
推荐指数⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐❌ 不推荐❌ 不推荐⭐⭐

💡 架构师建议

首选方案:对于大多数现代前端项目,优先使用原生 Intl.NumberFormat。它无需依赖,支持所有主流浏览器,且性能最佳。

特定场景选择:

  • 数据可视化:选择 d3-format。它与图表库配合最好,格式控制最精细。
  • 复杂数学计算:选择 mathjs。如果你已经用它做计算,顺便用它格式化可以减少依赖。
  • 日志与模板:选择 sprintf-js。当你需要类似后端的字符串格式化逻辑时。
  • 旧项目维护:如果现有代码大量使用 numeral 或 accounting-js,建议制定计划迁移至 d3-format 或原生 API,以避免未来兼容性风险。

最终结论:库的选择应基于项目具体需求。不要为了简单的数字格式化引入重型库(如 mathjs),也不要在新项目中使用已停止维护的库(如 numeral)。保持依赖精简,优先利用原生能力。

如何选择: numeral vs format-number vs accounting-js vs d3-format vs mathjs vs sprintf-js

  • numeral:

    该库已正式停止维护,存在潜在的安全和兼容性风险。严禁在新项目中使用,现有项目应计划迁移至 d3-format 或原生 Intl.NumberFormat。

  • format-number:

    适用于只需要简单数字分隔且不希望引入重型依赖的场景。它的 API 直观,但功能相对基础,适合轻量级工具库。

  • accounting-js:

    适合维护旧项目,它提供了开箱即用的货币格式化功能,代码简单直观。但由于已多年未更新,缺乏对现代 locale 标准的支持,不建议在新架构中引入。

  • d3-format:

    如果你正在构建数据可视化应用或需要极高的格式控制精度,这是首选。它维护活跃,支持复杂的格式说明符,且与 D3 生态系统无缝集成。

  • mathjs:

    仅当你已经需要用到其强大的数学计算功能(如矩阵运算、单位转换)时才选择它。单纯为了格式化而引入它会导致包体积过大,得不偿失。

  • sprintf-js:

    当你需要类似 C 语言 printf 的字符串插值功能时使用,不仅仅是数字,还包括日期、对象等。它适合日志格式化或复杂模板字符串构建。

numeral的README

Numeral.js

A javascript library for formatting and manipulating numbers.

Website and documentation

Travis Build Status

Master Build Status

Develop Build Status

NPM

NPM

#CDNJS

CDNJS

Contributing

Important: Please create your branch from and submit pull requests to the develop branch. All pull requests must include the appropriate tests.

  1. Fork the library

  2. Install grunt

  3. Run npm install to install dependencies

  4. Create a new branch from develop

  5. Add your tests to the files in /tests

  6. To test your tests, run grunt

  7. When all your tests are passing, run grunt dist to compile and minify all files

  8. Submit a pull request to the develop branch.

Formats

Formats now exist in their own files and act more or less as plugins. Check out the bytes format for an example of how to create one.

Locales

When naming locale files use the ISO 639-1 language codes supplemented by ISO 3166-1 country codes when necessary.

Locale translations will not be merged without unit tests.

See the english unit tests for an example.

Changelog

2.0.6

Bug fix: Multi letter currency symbols and spacing

Added: Formatting of numbers with leading zeros

New format: Basic Point

Option: Added scalePercentBy100 (default: true) option to turn on/off scaling percentages

2.0.4

Bug fix: Incorrect abbreviations for values rounded up #187

Bug fix: Signed currency is inconsistent #89

2.0.2

Bug fix: Updated module definitions

2.0.1

Bug fix: Fixed regression for webpack/browserify/rollup

2.0.0

2.0.0 brings a lot of breaking changes and a reorganization of the repo, but also simplifies the api as well as the creating of custom formats.

Breaking change / Feature: All formats are now separate files. This makes it easy to create custom formats, and will also allow for custom builds with only certain formats. (Note: The built numeral.js still contains all formats in the repo).

Breaking change / Feature: All formats and locales are now loaded using numeral.register(type, name, {})

Breaking change: All language now renamed to locale and standardized to all lowercase filenames

Breaking change: The locale function no longer loads locales, it only sets the current locale

Breaking change: The unformat function has been removed numeral().unformat(string) and now happens on numeral init numeral(string)

Breaking change / Feature: Bytes are now formatted as: b (base 1000) and ib (base 1024)

Breaking change: numeral(NaN) is now treated the same as numeral(null) and no longer throws an error

Feature: Exponential format using e+ or e-

Bug fix: Update to floating point helpers (Note: Numeral does not fix JS floating point errors, but look to our tests to see that it covers quite a few cases.)

1.5.6

Bug fix: numeral converts strings to numbers

Bug fix: Null values return same as 0

1.5.5

Contained breaking changes, recommended to use 1.5.6

Bug fix: Switch bytes back to b and change iecBinary to ib, and calculate both using 1024 for backwards compatibility

1.5.4

Contained breaking changes, recommended to use 1.5.6

Tests: Changed all tests to use Mocha and Chai

Tests: Added browser tests for Chrome, Firefox, and IE using saucelabs

Added reset function to reset numeral to default options

Added nullFormat option

Update reduce polyfill

Added Binary bytes

Bug fix: Fixes problem with many optional decimals

1.5.3

Added currency symbol to optionally appear before negative sign / open paren

Added float precision math support

Added specification of abbreviation in thousands, millions, billions

1.5.2

Bug fix: Unformat should pass through if given a number

Added a mechanism to control rounding behaviour

Added languageData() for getting and setting language props at runtime

1.5.1

Bug fix: Make sure values aren't changed during formatting

1.5.0

Add defaultFormat(). numeral().format() uses the default to format if no string is provided

.unformat() returns 0 when passed no string

Added languages.js that contains all languages

Bug fix: Fix bug while unformatting ordinals

Add format option to always show signed value

Added ability to instantiate numeral with a string value of a number

1.4.9

Bug fix: Fix bug while unformatting ordinals

1.4.8

Bug fix: Throw error if language is not defined

1.4.7

Bug fix: Fix typo for trillion

1.4.6

Bug fix: remove ' from unformatting regex that was causing an error with fr-ch.js

1.4.5

Add zeroFormat() function that accepts a string for custom formating of zeros

Add valueOf() function

Chain functionality to language function

Make all minified files have the same .min.js filename ending

1.4.1

Bug fix: Bytes not formatting correctly

1.4.0

Add optional format for all decimals

1.3.4

Remove AMD module id. (This is encouraged by require.js to make the module more portable, and keep it from creating a global)

1.3.3

AMD define() compatibility.

1.3.2

Bug fix: Formatting some numbers results in the wrong value. Issue #21

1.3.1

Bug fix: Minor fix to unformatting parser

1.3.0

Add support for spaces before/after $, a, o, b in a format string

Bug fix: Fix unformat for languages that use '.' in ordinals

Bug fix: Fix round up floating numbers with no precision correctly.

Bug fix: Fix currency signs at the end in unformat

1.2.6

Add support for optional decimal places

1.2.5

Add support for appending currency symbol

1.2.4

Add support for humanized filesizes

1.2.3

Bug Fix: Fix unformatting for languages that use '.' as thousands delimiter

1.2.2

Changed language definition property 'money' to 'currency'

1.2.1

Bug fix: Fix unformatting non-negative abbreviations

1.2.0

Add language support

Update testing for to include languages

1.1.0

Add Tests

Bug fix: Fix difference returning negative values

1.0.4

Bug fix: Non negative numbers were displaying as negative when using parentheses

1.0.3

Add ordinal formatting using 'o' in the format

1.0.2

Add clone functionality

1.0.1

Added abbreviations for thousands and millions using 'a' in the format

1.0.0

Initial release

Acknowlegements

Numeral.js, while less complex, was inspired by and heavily borrowed from Moment.js

License

Numeral.js is freely distributable under the terms of the MIT license.

Copyright (c) 2012 Adam Draper

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.