Nodes/WAS Node Suite v3/Number Expression
ComfyUI Node Runs on cloud

Number Expression

A real calculator node, no Python sandbox required

By WASasquatch·Created 3 years ago·Updated 4 days ago· 1,844
Number Expression
  • a
  • b
  • c
  • d
  • e
  • f
  • g
  • h
  • i
  • j
  • k
  • l
  • m
  • n
  • o
  • p
  • q
  • r
  • s
  • t
  • u
  • v
  • w
  • x
  • number
  • float
  • int
  • boolean
  • text
expressiona + b
decimals6
on_errorerror

Every ComfyUI user eventually needs to do math that the primitive math nodes can't express in one step. Number Expression is the node that lets you write (a * b) / 2 + c instead of chaining three Math nodes and squinting at the wires. You type a formula, it evaluates it, and the answer leaves as a NUMBER, a FLOAT, an INT, a BOOLEAN and text all at once.

It's the middle ground between ComfyUI's fiddly single-operation math nodes and the "power user runs a Python node" approach. The nice bit is the sandboxing: this is not a general-purpose code runner. Only arithmetic reads - the allowed function list is short and named, and anything else is refused by name before it runs. If you've ever pasted a workflow containing a PythonScript node you didn't fully trust, you can see why that's a feature.

The expression language

Slots a through x give you 24 numbers, each typed in or wired from elsewhere. A slot the expression never mentions is simply ignored; unconnected slots use their widget value. Then the expression box is your formula:

(a * b) / 2 + c
clamp(a, 0, 1)
round(a / b, 2)
a if a > b else b

Functions available: min, max, abs, round, floor, ceil, sqrt, clamp(v, lo, hi), lerp(a, b, t), sign, log, log2, log10, exp, sin, cos, tan, atan2, hypot, degrees, radians. Constants pi, e and tau are there, comparisons work, and and/or combine conditions. The expression box takes several lines joined into one, and # starts a comment.

The boolean output deserves a mention: a > b answers 1 or 0 on the number outputs, but the BOOLEAN socket carries the real true/false - wire that into a switch and you've built a comparison node too.

Outputs, and one honest caveat

  • number - the answer on the NUMBER wire, whole where it came out whole.
  • float / int - the same answer as a decimal and as an integer (int cuts the fraction off rather than rounding, so 3.9 leaves as 3).
  • boolean - false when the answer is 0, true otherwise.
  • text - the answer written out (4.5 or 7), which is what you feed into a filename prefix or a text join.

Watch the int behavior: round(3.7) gives 4.0 on the float side but 3 on the int side because int truncates. Use round() if you actually want rounding - the tooltips make the distinction explicit and it's a real trap.

Setup and gotchas

decimals sets how many places a fractional answer is rounded to (6 = 0.333333, 2 = 0.33, 0 = whole). on_error decides what happens when the expression is refused or impossible: error stops the run and names the cause; zero logs it and answers 0. The one genuinely foot-gun case is a / b with b at 0 - that stops the run unless on_error is zero.

This node ships in WAS Node Suite v3 - install via ComfyUI Manager (search WAS Node Suite v3) or:

cd ComfyUI/custom_nodes
git clone https://github.com/WASasquatch/was-node-suite-comfyui

Restart after cloning; you need ComfyUI 0.14.0+ and Python 3.10+. No extra packages - v3's rewrite deliberately dropped the pack's old twenty-dependency install, and nothing gets downloaded on startup.

Honestly, the use case that keeps this node on my canvas is filenames and captions. Build a frame number or a scaled value, push the text output into a save prefix, and every render names itself correctly.

CategoryWAS Suite/Number/Operations

Inputs (27)

NameTypeDefaultDescription
expressionSTRINGa + bThe formula, over `a` to `x`. Eg: `(a * b) / 2 + c`. Functions: min max abs round floor ceil sqrt clamp lerp sign log log2 log10 exp sin cos tan atan2 hypot degrees radians, plus pi, e and tau. `a > b` comes out as 1 or 0; `#` starts a comment.
aoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `a` stands for. Type it here or wire one in. Unconnected slots use the widget, and a slot the expression never names is ignored.
boptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `b` stands for. Type it here or wire one in. `a / b` with b at 0 stops the run unless on_error is set to zero.
coptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `c` stands for. Type it here or wire one in. Handy as the offset in `(a * b) / 2 + c`.
doptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `d` stands for. Type it here or wire one in. The fourth value, free for a limit such as `clamp(a, c, d)`.
eoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `e` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
foptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `f` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
goptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `g` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
hoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `h` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
ioptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `i` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
joptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `j` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
koptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `k` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
loptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `l` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
moptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `m` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
noptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `n` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
ooptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `o` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
poptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `p` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
qoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `q` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
roptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `r` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
soptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `s` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
toptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `t` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
uoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `u` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
voptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `v` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
woptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `w` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
xoptFLOAT,NUMBER,INT0-18446744073709550000–18446744073709550000The number `x` stands for. Type it here or wire one in. An unconnected slot uses its widget, and a slot the expression never names is ignored.
decimalsoptINT60–15Decimal places a fractional answer is rounded to. 6 = 0.333333, 2 = 0.33, 0 = whole, so 3.7 comes out 4.0. It also clears the trailing 0.0000000001 that decimal arithmetic leaves behind. A whole answer is untouched.
on_erroroptCOMBOerrorWhat a refused or impossible expression does. `error` = stop the run and name the cause, `zero` = log it and answer 0. Pick `zero` where a division by zero is expected on some frames of a batch.

Outputs (5)

NameTypeDescription
numberNUMBERThe answer on the NUMBER wire, whole where it came out whole. A comparison answers 1 or 0.
floatFLOATThe same answer as a decimal, so 7 leaves here as 7.0.
intINTThe same answer with its fraction cut off rather than rounded, so 3.9 leaves here as 3. Held to the range a whole-number socket carries.
booleanBOOLEANfalse when the answer is 0, true for anything else. Wire it to a switch to branch on `a > b`.
textSTRINGThe answer written out, as `4.5` or `7`. Feed it to a filename prefix or a text join.