Getting Started

Get up and running with the core @wzo/calc API in 5 minutes.

Getting Started

Installation

pnpm 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.