Skip to content

为什么选择 a-calc

一句话总结

a-calc 是地表最强的 JavaScript 精度计算和数字格式化库。

不是之一,没有并列。

精度问题:JavaScript 的原罪

javascript
// JavaScript 原生计算
0.1 + 0.2                  // 0.30000000000000004
0.3 - 0.1                  // 0.19999999999999998
0.1 * 0.2                  // 0.020000000000000004
0.3 / 0.1                  // 2.9999999999999996

这在金融、电商、数据报表等场景是致命的。

javascript
// a-calc 的答案
import { calc } from 'a-calc'

calc('0.1 + 0.2')          // '0.3'
calc('0.3 - 0.1')          // '0.2'
calc('0.1 * 0.2')          // '0.02'
calc('0.3 / 0.1')          // '3'

性能:10 倍碾压

50 万次计算相对性能
a-calc3.6s10x
mathjs v135.7s1.6x
mathjs v1236s1x (基准)

这不是优化,是代差。

功能:一个顶三个

功能a-calcmathjsnumeraldecimal.js
精度计算
表达式解析
千分位格式化
百分比格式化
国际化数字格式
紧凑格式缩写
单位计算
单位转换
条件表达式
链式计算
表达式预编译
多计算引擎
包大小20KB150KB18KB12KB

mathjs + numeral + decimal.js = 180KB,功能还不如 a-calc 的 20KB。

核心能力一览

1. 计算 + 格式化一步到位

javascript
// 其他库:计算完还要格式化
const result = mathjs.evaluate('price * quantity')
const formatted = numeral(result).format('0,0.00')

// a-calc:一行搞定
calc('price * quantity | =2,', { price: 1234.5, quantity: 2 })
// '2,469.00'

2. 四种舍入规则

javascript
calc('1.125 | ~-=2')   // '1.12' - 截断
calc('1.125 | ~+=2')   // '1.13' - 进位
calc('1.125 | ~5=2')   // '1.13' - 四舍五入
calc('1.125 | ~6=2')   // '1.12' - 银行家舍入(四舍六入五取偶)

银行家舍入是金融行业标准,其他库要么不支持,要么需要额外配置。

3. 全球数字格式

javascript
calc('1234567.89 | !t:en')      // '1,234,567.89' 英文/国际
calc('1234567.89 | !t:eu')      // '1.234.567,89' 欧式
calc('1234567.89 | !t:indian')  // '12,34,567.89' 印度
calc('1234567.89 | !t:wan')     // '1,2345,678.89' 万进制

4. 紧凑格式智能缩写

javascript
calc('1234567 | !c')            // '1.23M'
calc('12345 | !c:wan')          // '1.23万'
calc('1073741824 | !c:storage') // '1GB'

5. 三种计算引擎

javascript
import { set_config, calc } from 'a-calc'

// Decimal 模式:50 位精度,功能最全
set_config({ _compute_mode: 'decimal' })

// BigInt 模式:大整数无损,性能更好
set_config({ _compute_mode: 'bigint' })
calc('12345678901234567890 * 2')  // 完全精确

// WASM 模式:极致性能
set_config({ _compute_mode: 'wasm' })

6. 链式计算

javascript
import { cplus, cmul } from 'a-calc'

// 购物车计算
cplus(99.9, 199, 49.5)   // 商品价格
  .mul(0.9)               // 9折
  .sub(20)                // 满减
  .mul(1.06)              // 税费
  ('=2,')                 // '296.33'

7. 条件表达式

javascript
calc('score >= 60 ? "及格" : "不及格"', { score: 75 })  // '及格'

calc(`
  score >= 90 ? "A" :
  score >= 80 ? "B" :
  score >= 70 ? "C" :
  score >= 60 ? "D" : "F"
`, { score: 85 })  // 'B'

8. 单位计算与转换

javascript
// 带单位计算
calc('100元 + 50元', { _unit: true })  // '150元'

// 单位转换
calc('100 | !ua:元', {
  _unit_convert_out: { '元': { '分': 0.01 } }
})  // '1元' (100分 → 1元)

9. 内置数学函数

javascript
calc('sqrt(16)')           // '4'
calc('sin(90)')            // '1' (默认角度制)
calc('pow(2, 10)')         // '1024'
calc('max(1, 5, 3)')       // '5'
calc('round(3.7)')         // '4'
calc('abs(-5)')            // '5'

10. 多路取值(Fallback)

javascript
// 优先取 a,a 为空则取 b
calc('(a | b) + 1', { b: 10 })       // '11'
calc('(a | b) + 1', { a: 5, b: 10 }) // '6'

// 多级 fallback
calc('(a | b | c)', { c: 100 })     // '100'

11. 调试模式

javascript
calc('a + b * c', { a: 1, b: 2, c: 3, _debug: true })
// 控制台输出完整的计算过程和中间结果

实战场景

金融计算

javascript
// 复利计算
calc('principal * pow(1 + rate, years) | =2,', {
  principal: 10000,
  rate: 0.05,
  years: 3
})  // '11,576.25'

// 银行家舍入
calc('amount | ~6=2', { amount: 2.225 })  // '2.22'
calc('amount | ~6=2', { amount: 2.235 })  // '2.24'

电商价格

javascript
// 满减 + 折扣
calc('(price * quantity - fullCut) * discount | =2', {
  price: 199,
  quantity: 3,
  fullCut: 50,
  discount: 0.9
})  // '491.10'

数据报表

javascript
// 批量格式化
const data = [1234567, 2345678, 3456789]
data.map(n => calc(`${n} | =2,`))
// ['1,234,567.00', '2,345,678.00', '3,456,789.00']

// 涨跌幅
calc('change | %=2+', { change: 0.0523 })   // '+5.23%'
calc('change | %=2+', { change: -0.0312 })  // '-3.12%'

股票交易量

javascript
calc('volume | !c:wan', { volume: 12345678 })  // '1234.56万'
calc('volume | !c !ua:股', { volume: 1234567 }) // '1.23M股'

迁移成本:几乎为零

javascript
// 从 mathjs 迁移
// Before
mathjs.evaluate('1 + 2 * 3')
// After
calc('1 + 2 * 3')

// 从 numeral 迁移
// Before
numeral(1234567).format('0,0.00')
// After
calc('1234567 | =2,')

// 从 decimal.js 迁移
// Before
new Decimal('0.1').plus('0.2').toString()
// After
calc('0.1 + 0.2')

总结

维度a-calc 的答案
精度50 位 Decimal / 无限 BigInt / 28 位 WASM
性能比 mathjs 快 10 倍
体积20KB,比 mathjs 小 7 倍
格式化千分位、百分比、科学计数、紧凑格式、国际化
舍入截断、进位、四舍五入、银行家舍入
易用性计算 + 格式化一行代码

a-calc 不是在某个维度上领先,而是在所有维度上碾压。

这就是为什么选择 a-calc。

基于 MIT 许可发布