Getting Started
Get up and running with the core @wzo/calc API in 5 minutes.
Getting Started
Installation
pnpm add @wzo/calc
yarn add @wzo/calc
npm install @wzo/calc
bun add @wzo/calc
Usage
quick-start.ts
import { addStr, calc, calcAvg, calcSum, chainAdd, div, divStr, fmt, setConfig } from '@wzo/calc'
// Global config: call once at app entry — shared across the entire application (fmt fallback / division precision)
// setConfig({ _error: 0, _precision: 20 })
// Precision arithmetic (no floating-point errors)
calc('(0.1 + 0.2) * 3') // "0.9"
// Variables are interpolated into the expression as literals
const { price, qty } = { price: 9.9, qty: 3 }
calc(`${price} * ${qty}`, { _fmt: { decimals: 2 } }) // "29.70"
// Type-friendly formatting
fmt(1234567, { decimals: 2, thousands: true }) // "1,234,567.00"
fmt(1234567, { compact: 'zh', decimals: 2 }) // "123.45万"
// Display fmt: supports expressions + error fallback (dirty data won't crash the page)
fmt(`${price} * ${qty}`, { decimals: 2 }) // "29.70"
fmt('bad expr', { _error: '-' }) // "-"
// High-precision strings: no precision loss for amounts or large integers
addStr('0.1', '0.2') // "0.3"
addStr('9007199254740993', '1') // "9007199254740994"
// Chaining
chainAdd(10).sub(3).mul(2)() // "14"
// Aggregation (automatically skips null / undefined)
calcSum('price', [{ price: 10 }, { price: 20 }]) // "30"
// Division precision: uses global _precision by default; override per call at the end (does not pollute global state)
div(100, 3, { _precision: 2 }) // 33.33
1. Precision arithmetic
The most common use case — fixing JS floating-point precision loss:
calc('0.1 + 0.2') // "0.3"
calc('0.1 + 0.2 * 0.3 / 0.4 * (0.5 + 0.6)') // "0.265"
2. Use template interpolation instead of variables
calc does not support variables — just interpolate values directly into the expression:
const a = 1
const b = 2
calc(`${a} + ${b}`) // "3"
calc(`${9.9} * ${3}`) // "29.7"
3. Expression + formatting
Pass an IFormat object via _fmt to format the result:
calc('9.9 * 3', { _fmt: { decimals: 2 } }) // "29.70"
calc('1234567', { _fmt: { decimals: 2, thousands: true } }) // "1,234,567.00"
4. Direct formatting
fmt(1234567, { decimals: 2, thousands: true }) // "1,234,567.00"
fmt(1234567, { compact: true }) // "1.23M"
fmt(1234567, { compact: 'zh' }) // "123.45万"
fmt(0.5, { output: 'percent' }) // "50%"
5. Chaining
import { chainAdd, chainMul } from '@wzo/calc'
chainAdd(10).sub(3).mul(2)() // "14"
chainAdd(1000, 2000)({ decimals: 2, thousands: true }) // "3,000.00"
chainMul(2, 3).add(4)() // "10"
6. Aggregation
calcSum('price', [{ price: 10 }, { price: 20 }]) // "30"
calcAvg([1, 2, 3]) // "2"
7. Math functions
Expressions support abs / min / max / clamp / pow / mod / floor / ceil / round and more (all exact):
calc('max(3, 5) * 2') // "10"
calc('clamp(150, 0, 100)') // "100"
Expressions are pure arithmetic — write conditionals in JS outside the expression:
a > 10 ? calc(`${a} * 0.9`) : String(a).Pass strings for precision-sensitive values
The library uses BigInt throughout for exact computation, but this only helps if the value you pass in is already accurate. JS number literals can be corrupted by floating-point representation before they even reach the function — no library can recover from that:
calc(`${0.1 + 0.2} + 0`) // 0.1+0.2 is already 0.30000000000000004 before interpolation
addStr(9007199254740993, 0) // "9007199254740992" ← JS has already rounded the number literal
Plain decimals like
9.9 or 0.1 are fine as number; but for monetary values, large integers, or results from other computations, pass strings to avoid precision loss at the call site.// ✅ Safe
addStr('9007199254740993', '0') // "9007199254740993"
calc('0.1 + 0.2') // "0.3" (string literal — no precision loss)
Mixing number and string is allowed (add(0.1, '0.2') is valid) — safety depends solely on whether the precision-sensitive value was passed as a number or a string.