calculate
Evaluate arithmetic expressions or multi-line programs in fixed-point, floating-point, or rational modes. Each result includes exactness and precision labels.
Instructions
Evaluate an expression (or short program) in one numeric type; return value + precision.
Use `calculate` when you want the VALUE of an expression. To instead see WHERE a
surprising answer rounded or overflowed — the per-node parse tree with each
sub-result — use `analyze`; to find the variable value(s) that drive an
expression to a root or extremum, use `solver`. All three share this expression
language and `mode`/`min_fixed_point_precision` arguments.
`mode` is the numeric type the WHOLE calculation runs in — every intermediate
result behaves exactly as that type would, so float rounding, fixed-point
scale, and rational exactness each show through. Modes:
fixed-point (default) exact scaled integer; money / ERC-20-safe; alias decimal
floating-point IEEE-754 double; ~15-17 sig. digits; aliases float64, double, float, ieee754
rational exact numerator/denominator; no irrationals; aliases fraction, frac
Grammar. Binary `+ - * / // %`; unary prefix `+ - ~`; `**` is POWER,
right-assoc, binds tighter than unary minus: -2**2 == -(2**2). Bitwise
`& | ^` (^ is XOR, NOT power) and `~` (NOT) work in EVERY type, on its own
stored bits (float's 64-bit IEEE pattern, fixed-point's mantissa, rational's
numerator/denominator). Both operands
of a binary op must share ONE type — there is no implicit promotion. Group
with `( )`. Functions: call as `name(arg, ...)` — e.g. `sqrt`, `sin`, `sum`;
each argument evaluates in the active type. For the full set and their
argument counts call `help('functions')`. Constants: `pi` and `e` are usable
bare (no parentheses), e.g. `2*pi`; assigning to them is an error. Literals: decimals
`12 3.14 .5 1e3 2.5e-4`; base integers
`0x1F 0b1010 0o17`; fixed-point `M@D == M x 10^-D`, where M MUST be
base-prefixed (0x/0o/0b) — a DECIMAL mantissa is INVALID: both `123@2` and
`123.45@2` error; write a decimal value as its digits (e.g. 123.45), never
with `@`. (`0x59682F00@9` = 1.5, `0xDE0B6B3A7640000@18` = 1 ETH.)
Variables & multi-line programs. Assign with `name = expr` (name is an
identifier `[A-Za-z_][A-Za-z0-9_]*`); a bare `name` reads it back, and reading
a name that was never assigned is an error. An assignment is itself an
expression — its value is the right-hand side — so `x = 2 + 3` returns 5 and
also binds `x`. Pass SEVERAL statements as one `expression` by separating them
with NEWLINES (`
): they run top to bottom sharing one variable scope, so a later line sees earlier bindings. EVERY bare-expression line is answered, in source order, in the valuesarray (below); assignment lines run silently for their bindings and are NOT echoed — except the final line, which is always the program's result and so is always echoed. When more than one line is answered, the top-level valueis a multi-line transcript, one = per answered line; a single answered line keepsvalueas just that result. E.g. "x = 10
y = x * 2
y + 1"returns 21 (onlyy + 1is a bare line), while "x = 10
(x - 1) / (x + 1)
(x + 1) / 100.0"answers both divisions. Scope lasts for the one call only — bindings do not carry over to the nextcalculate`.
Returns a dict: `value` is the result rendered as a string and ANNOTATED with
its precision verdict — "(exact)" when the result is the true value, else
"(inexact, rounded to N decimals)" — so e.g. `/` cannot silently mislead by
looking exact when it rounded. `value_hex_dump` is that same value in hex (the
bit-backed representation): fixed-point as M@D (mantissa in whole-byte hex,
`@scale` dropped at scale 0), floating-point as the raw 64-bit IEEE-754
pattern, and NULL in rational mode (a numerator/denominator pair has no single
integer to dump). `mode` is the RESOLVED numeric type the call ran in — always
the canonical name even when you passed an alias (e.g. "double" reads back as
"floating-point"), so the reply stands on its own. The exactness/scale facts
are also returned as separate fields: `exact` (bool — did the mode hold the
true value) and `precision` (the fixed-point decimal scale, or null when the
mode has none). NOTE: floating-point conservatively reports `exact: false` for
every result today, including ones a double holds exactly. `values` is the per-line
breakdown: an array with one object per answered line, in source order, each
`{source, value, value_hex_dump, exact, precision, offered_precision}` — `source` is
the re-rendered expression and the other fields mirror the top-level ones for that one
line. The LAST entry is the program's result, so its fields equal the top-level
`value_hex_dump`/`exact`/`precision`/`offered_precision` (and, for a single answered
line, the top-level `value`). On failure `value`/`value_hex_dump`/`mode`/`exact`/
`precision`/`offered_precision`/`values` are null and `error` carries a plain,
self-contained message — what went wrong (a malformed expression, a domain error,
or an unknown mode with the valid list). It reads as prose, not a log line; only
the inexact-abort diagnostic names its source line, and in prose. On success
`error` is null. For the full reference call `help`.
`min_fixed_point_precision` floors the fixed-point result at that many decimal
places: every operand is held at no fewer than that many fractional digits, so
a `/` that would otherwise round at scale 0 keeps more decimals. It is valid
ONLY in fixed-point mode (the other modes have no decimal scale) and must be a
non-negative integer; either violation is an `error`. Omit it (null) for no
floor.
`inexact_handling` chooses what happens when a result is INEXACT:
continue-and-report (default) evaluate normally and let the verdict surface
in `value`/`exact`; never reject. Aliases: continue, report.
abort-on-inexact stop and FAIL the moment any sub-result is inexact. The
call returns no value — `error` instead carries a
diagnostic naming the source line and laying out the
operation that went inexact in computed VALUES (e.g.
`1.00 / 3.00 = 0.33`), then how to enable inexact
calculations if you do want the rounded answer. Use it
when an approximate answer is unacceptable and you want to
be told precisely what and where, rather than silently
trusting a rounded figure. Aliases: abort, strict, exact-only.
An unknown value is an `error` listing the valid choices. Note floating-point
reports every result inexact, so abort-on-inexact there fails on the first value.
`offered_precision` is a what-if nudge, present (non-null) ONLY on an inexact
fixed-point result when you did NOT pass min_fixed_point_precision: it shows the
SAME expression at a few more decimals so you see the digits the rounding hid.
It is a nested object `{mode, min_fixed_point_precision, value, value_hex_dump,
exact}` mirroring the top-level reply — its `mode` is always "fixed-point", its
min_fixed_point_precision is the argument to pass to GET that fuller value, its
`value` is what you'd get back (annotated with its OWN precision verdict, since
the offered value may itself still be inexact — e.g. 10/3 never terminates),
and `value_hex_dump` is that offered value in hex. It is NOT the answer to the
call you made (that stays in the top-level `value`); it is null whenever there
is nothing to offer. Each `values` entry carries its OWN `offered_precision` under
the same gate, so every answered line steers independently.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Numeric type the WHOLE calculation runs in: 'fixed-point' (default; exact scaled integer, money/ERC-20-safe; alias 'decimal'), 'floating-point' (IEEE-754 double; aliases 'float64', 'double', 'float', 'ieee754'), or 'rational' (exact numerator/denominator; aliases 'fraction', 'frac'). Note 'decimal' resolves to fixed-point, NOT a decimal float. `help('types')` lists the full set. | fixed-point |
| expression | Yes | The expression, or a newline-separated multi-line program (`name = expr` assignments sharing one scope), to evaluate. | |
| inexact_handling | No | What to do when a result is inexact: 'continue-and-report' (default; evaluate and let the precision verdict surface) or 'abort-on-inexact' (fail on the first inexact sub-result). | continue-and-report |
| min_fixed_point_precision | No | Floor fixed-point results at this many decimal places (non-negative integer). Valid ONLY in fixed-point mode; null for no floor. |