Standalone Functions

add / sub / mul / div + addStr / subStr / mulStr / divStr — direct calls without expressions or chaining.

Standalone Functions

The most direct form — no expression strings, no chaining, just add two numbers.

Try It Live

add(0.1, 0.2) // 0.3   (number)
addStr('0.1', '0.2') // "0.3" (string, exact)
divStr('1', '3') // "0.333..." (up to 50 digits)
在线运行⌘/Ctrl + Enter 运行

Number-returning Variants

add / sub / mul / div:

add
(0.1, 0.2) // 0.3
sub
(1, 0.3) // 0.7
mul
(3, 4, 5) // 60
div
(10, 4) // 2.5
// multiple arguments are reduced
add
(1, 2, 3, 4) // 10
mul
(2, 3, 4) // 24
These functions use precision arithmetic internally but convert the final result with Number(). Results are strictly correct within the Number safe range — precision is lost beyond that range.

Passing Arrays

add / sub / mul / div (and addStr… / chainAdd…) are all variadic — spread an array with ... to pass it as arguments:

const 
nums
= [0.1, 0.2, 0.3]
add
(...
nums
) // 0.6
addStr
(...
nums
) // "0.6"
chainAdd
(...
nums
)() // "0.6"
// sum a list of prices (with precision) const
prices
= ['9.99', '19.99', '4.95']
addStr
(...
prices
) // "34.93"
const nums = [0.1, 0.2, 0.3]
addStr(...nums) // "0.6"

const prices = ['9.99', '19.99', '4.95']
addStr(...prices) // "34.93"
在线运行⌘/Ctrl + Enter 运行

String-returning Variants (Str suffix)

addStr / subStr / mulStr / divStr — the Str suffix means "returns a high-precision string with no precision loss":

addStr
('0.1', '0.2') // "0.3"
mulStr
('0.1', '0.2') // "0.02"
divStr
('1', '3') // "0.3333333333333333333333333333333333333333333333333"
// large integers are also exact
addStr
('99999999999999999', '1') // "100000000000000000"
mulStr
('9999999999', '9999999999') // "99999999980000000001"

Power / Root / Modulo (sqrt / pow / mod)

Beyond the four basic operations, three more standalone functions are available — each with a number-returning form and a Str (string) form:

sqrt
(4) // 2
sqrtStr
('2', {
_precision
: 6 }) // "1.414214"
pow
(2, 10) // 1024
pow
(2, -1) // 0.5 (negative exponent ⇒ reciprocal)
powStr
('1.02', 5) // "1.1040808032"
mod
(-7, 3) // -1 (remainder carries the dividend's sign, like JS %)
modStr
('5.5', '2') // "1.5"
sqrt and negative-exponentpow are irrational/repeating, so they round to the division precision (default 50). Pass a trailing { _precision } to override it for that call. pow with a non-negative integer exponent and mod are exact. The exponent of pow must be an integer; sqrt of a negative number throws.

When to Use Which

ScenarioUse
Result feeds directly into business logic (comparison, database storage, etc.)add / sub / mul / div (number)
Result will be displayed to the useraddStr / subStr / mulStr / divStr (string, pair with fmt)
Result is a very large number or highly precise decimalMust use the Str variants — Number will lose precision

Input Precision Pitfalls

The discussion above is about output: number-variant results can lose precision when they exceed the Number safe range. But there is also a subtler input problem —

Mixing numbers and strings is perfectly legal (add(0.1, '0.2') works fine), but keep in mind: a value can already be corrupted by JS floating-point before it even reaches the function — no library can recover that.

// number literals are already broken before you pass them
addStr(0.1 + 0.2, 0) // "0.30000000000000004" ← the input itself has this value
addStr(9007199254740993, 0) // "9007199254740992"  ← beyond safe range, literal is already rounded

// pass as strings to preserve full precision end-to-end
addStr('0.1', '0.2') // "0.3"
addStr('9007199254740993', '0') // "9007199254740993"
Whether precision is lost does not depend on whether you mix numbers and strings — it depends on whether you wrote the precision-sensitive value as a number or a string. For monetary amounts, large integers, or intermediate results from other calculations, always pass them as strings.