$math — Math Directive
Evaluates arithmetic expressions and applies named math functions using safe expression parsing — no JavaScript engine required. Ideal for Simple calculations inline without scripting overhead.
| Property | Value |
|---|---|
| Directive name | math |
| Required isolation level | Safe |
| Project | Functions.Services |
| Syntax form | $math.functionName(arg1, arg2, ...) or arithmetic path |
| Precision | Decimal arithmetic — no floating-point drift |
When to use $math vs $js
Use
$math for straightforward arithmetic and named functions on already-resolved values. Use $js when you need conditionals, loops, or string manipulation alongside the math. $math runs at Safe isolation and is faster — no engine startup cost.
Built-in Functions Reference
| Function | Signature | Returns | Example |
|---|---|---|---|
round | round(value, decimals) | Decimal | $math.round(12.456, 2) → 12.46 |
floor | floor(value) | Decimal | $math.floor(12.9) → 12 |
ceil | ceil(value) | Decimal | $math.ceil(12.1) → 13 |
abs | abs(value) | Decimal | $math.abs(-45.5) → 45.5 |
min | min(a, b) | Decimal | $math.min(10, 20) → 10 |
max | max(a, b) | Decimal | $math.max(10, 20) → 20 |
add | add(a, b) | Decimal | $math.add(100, 25) → 125 |
sub | sub(a, b) | Decimal | $math.sub(100, 25) → 75 |
mul | mul(a, b) | Decimal | $math.mul(100, 0.2) → 20 |
div | div(a, b) | Decimal | $math.div(100, 4) → 25 |
mod | mod(a, b) | Decimal | $math.mod(17, 5) → 2 |
pct | pct(value, percent) | Decimal | $math.pct(500, 20) → 100 |
pctOf | pctOf(part, total) | Decimal (0–100) | $math.pctOf(25, 100) → 25 |
clamp | clamp(value, min, max) | Decimal | $math.clamp(150, 0, 100) → 100 |
pow | pow(base, exponent) | Decimal | $math.pow(2, 8) → 256 |
sqrt | sqrt(value) | Decimal | $math.sqrt(144) → 12 |
Using Resolved Values as Arguments
Arguments to $math functions can themselves be BizFirst expressions. The orchestrator resolves inner expressions first (via multi-pass), then passes results to the math function:
VAT on input amount — resolves input first, then calculates
{@ $math.pct({@ $input.current.netAmount }, 20) }
Equivalent to: netAmount × 0.20
Complex Scenarios
Scenario 1 — Gross Pay Calculation from Rate and Hours
Gross pay
{@ $math.round(mul({@ $input.current.hourlyRate }, {@ $input.current.hoursWorked }), 2) }
hourlyRate × hoursWorked, rounded to 2dp
Scenario 2 — Invoice Total with VAT
// Subtotal field
{@ $math.round(mul({@ $input.current.qty }, {@ $input.current.unitPrice }), 2) }
// VAT amount (20%)
{@ $math.pct({@ $var.subtotal }, 20) }
// Grand total
{@ $math.add({@ $var.subtotal }, {@ $var.vatAmount }) }
Scenario 3 — Prorated Salary for Partial Month
// Working days in month from input, standard working days in month = 22
// Prorated monthly salary:
{@ $math.round(
mul(
div({@ $input.current.monthlySalary }, 22),
{@ $input.current.daysWorked }
), 2
) }
// (monthlySalary / 22) × daysWorked, rounded to 2dp
Scenario 4 — Overtime Premium Calculation
// Standard hours = 40/week; overtime rate = 1.5×
// Regular pay
{@ $math.mul({@ $input.current.hourlyRate }, {@ $math.min({@ $input.current.hoursWorked }, 40) }) }
// Overtime hours (if any)
{@ $math.max(sub({@ $input.current.hoursWorked }, 40), 0) }
// Overtime pay (at 1.5×)
{@ $math.mul({@ $var.overtimeHours }, mul({@ $input.current.hourlyRate }, 1.5)) }
Scenario 5 — Contribution Rate Clamped to Legal Maximum
// Pension contribution: employee elects a rate, but legislation caps it at 40%
{@ $math.clamp({@ $input.current.electedRate }, 0, 40) }
// e.g. input 55% → clamped to 40%
// Contribution amount from the clamped rate:
{@ $math.round(pct({@ $input.current.pensionablePay }, {@ $var.clampedRate }), 2) }
Scenario 6 — Percentage Completion Reporting
// After batch: report what percentage of records processed successfully
{@ $math.round(pctOf({@ $var.successCount }, {@ $var.totalCount }), 1) }
// "94.7" — percentage of records that succeeded
// With result embedded in a message:
Processed {@ $var.successCount } / {@ $var.totalCount } records
({@ $math.round(pctOf({@ $var.successCount }, {@ $var.totalCount }), 1) }% success rate)
Common Errors
| Error | Cause | Fix |
|---|---|---|
MathError: division by zero | div(x, 0) — denominator resolved to zero | Guard with $js or ensure denominator is non-zero; use @default:0 |
MathError: not a number | An argument resolved to a non-numeric string | Ensure upstream data is numeric; parse with $js if needed |
PathNotFound: unknownFn | Using a function name that doesn't exist | Check the built-in functions table above; use $js for custom logic |