- a
- b
- c
- d
- e
- f
- g
- h
- i
- j
- k
- l
- m
- n
- o
- p
- q
- r
- s
- t
- u
- v
- w
- x
- y
- z
- 数值
- 整数
- 布尔
The ugliest graphs I've seen aren't the ones with three upscalers chained together. They're the ones doing arithmetic. Multiply node, then an integer node, then a divide node, then a round node, then a reroute because the wires got confused - four nodes to express "half the width, rounded down to a multiple of 8."
QG_Math replaces all of that with a text field. You type floor(a / 2 / 8) * 8, wire your width into a, and you're done.
How it works, and why that matters
The node takes one required input, expr - a single-line STRING holding the formula - plus up to 26 optional inputs named a through z. Type INT, FLOAT, BOOLEAN for each, so an integer width, a float scale factor and a boolean toggle all plug in without complaint. Unwired variables count as 0.
The interesting part is how the expression gets evaluated. It does not call Python's eval. The pack ships a separate engine that parses your formula into an AST and then evaluates it node-by-node against a whitelist: numbers, variables, the constants pi/e/tau/inf, arithmetic, integer division, modulo, powers, unary minus, comparisons, and/or/not, the ternary form, lists, and a fixed set of math functions. Attribute access, subscripts, lambdas, comprehensions, assignments, f-strings, star-args and keyword args are refused outright.
That's a genuine security decision, not theatre. An expression in a shared workflow is external input, and clearing __builtins__ doesn't stop ().__class__ from walking out of the sandbox. Parsing to an AST and refusing unknown nodes closes that door. There are also sanity caps - 2000 characters, 400 AST nodes, exponent limited to 512, absolute values clamped around 1e15 - so nobody hands you a workflow with 10**10**10**10 in it and hangs your box.
You get three outputs from one result: 数值 (FLOAT, as computed), 整数 (INT, rounded and clamped to INT32), and 布尔 (BOOLEAN, true when non-zero). That third one is quietly the most useful: write a comparison like a > b and you have a condition generator for any switch or if-else node in the graph. The plumbing docs describe the whole logic family as "the graph as a small program" - this is the part that does the thinking.
Formulas worth keeping
round(a / b * 2, 2) # a ratio to two decimals
floor(a / 8) * 8 # snap a dimension to a multiple of 8
sqrt(a**2 + b**2) # diagonal
a if a > b else b # whichever is larger
(a > 1024) and (b > 1024)
That multiple-of-8 one earns its keep. Lots of models and VAEs are happier on grids of 8/16/32, and hand-editing width and height every time gets old.
Inputs and outputs, briefly
expr- the formula. Empty evaluates to 0.a…z- wire-only variables. Three slots show first, and connecting the last one grows another, up to 26. Integers, floats and booleans are all accepted.- Outputs:
数值,整数,布尔- same result, three shapes.
Installing
ComfyUI-QG-tools installs the boring way, and there's no model to download and nothing to pip install - the pack's requirements.txt is comments-only by design.
cd ComfyUI/custom_nodes
git clone https://github.com/live1617/ComfyUI-QG-tools
Full restart of ComfyUI, not a page refresh. You'll see the pack's banner in the console. The node is under QG-tools/逻辑 and searchable as math, expression, calculate or 数学. The author keeps a full function-by-function manual at docs/math.md in the repo, and the ? badge on the node shows an abbreviated version of the same cheat sheet.
Where people get burned
Unconnected variables are silently zero. Miss a wire on b and a / b doesn't error - it divides by zero, which does error, so that's fine. But a - b just quietly returns a, and you ship a wrong number that looks plausible. The three-slot layout means a, b, c are always visible, which helps: if the socket is drawn, check it's wired before you trust the result.
^ is not a power. That's XOR, Python semantics. 2 ^ 10 is 8, not 1024. Powers are **. The author flags this in the node's own help text, which tells you people have hit it.
Errors are loud, on purpose. A syntax error, an unknown function name, a division by zero - all raise with the original expression quoted in the red error box. That's the right behaviour. The alternative (returning 0 and moving on) produces a workflow that runs happily and generates 512×0 latents.
Full-width characters get normalized. If your IME gives you (, ×, ÷ or a 3:4 colon, the engine converts them before parsing. Convenient, and it means a copied formula from a chat window usually just works.
No number boxes. Every constant goes inside the expression. If you want a value you can scrub with the mouse or drive from another node, use the pack's numeric node and wire it into a.
Inputs (27)
| Name | Type | Default | Description |
|---|---|---|---|
| expr | STRING | 算式,例如 round(a / b * 2, 2)。 常量 pi、e、tau;支持 + - * / // % **、比较、and/or/not、三元表达式,以及 sqrt、round、min、max、log、sin 等 30 多个函数,逐个用法见 docs/math.md。留空时输出 0。 | |
| aopt | INT,FLOAT,BOOLEAN | 0 | 变量 a |
| bopt | INT,FLOAT,BOOLEAN | 0 | 变量 b |
| copt | INT,FLOAT,BOOLEAN | 0 | 变量 c |
| dopt | INT,FLOAT,BOOLEAN | 0 | 变量 d |
| eopt | INT,FLOAT,BOOLEAN | 0 | 变量 e |
| fopt | INT,FLOAT,BOOLEAN | 0 | 变量 f |
| gopt | INT,FLOAT,BOOLEAN | 0 | 变量 g |
| hopt | INT,FLOAT,BOOLEAN | 0 | 变量 h |
| iopt | INT,FLOAT,BOOLEAN | 0 | 变量 i |
| jopt | INT,FLOAT,BOOLEAN | 0 | 变量 j |
| kopt | INT,FLOAT,BOOLEAN | 0 | 变量 k |
| lopt | INT,FLOAT,BOOLEAN | 0 | 变量 l |
| mopt | INT,FLOAT,BOOLEAN | 0 | 变量 m |
| nopt | INT,FLOAT,BOOLEAN | 0 | 变量 n |
| oopt | INT,FLOAT,BOOLEAN | 0 | 变量 o |
| popt | INT,FLOAT,BOOLEAN | 0 | 变量 p |
| qopt | INT,FLOAT,BOOLEAN | 0 | 变量 q |
| ropt | INT,FLOAT,BOOLEAN | 0 | 变量 r |
| sopt | INT,FLOAT,BOOLEAN | 0 | 变量 s |
| topt | INT,FLOAT,BOOLEAN | 0 | 变量 t |
| uopt | INT,FLOAT,BOOLEAN | 0 | 变量 u |
| vopt | INT,FLOAT,BOOLEAN | 0 | 变量 v |
| wopt | INT,FLOAT,BOOLEAN | 0 | 变量 w |
| xopt | INT,FLOAT,BOOLEAN | 0 | 变量 x |
| yopt | INT,FLOAT,BOOLEAN | 0 | 变量 y |
| zopt | INT,FLOAT,BOOLEAN | 0 | 变量 z |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| 数值 | FLOAT | 算式的结果,原样输出(小数)。 |
| 整数 | INT | 同一个结果四舍五入成整数,夹在 INT32 范围内。 |
| 布尔 | BOOLEAN | 同一个结果是否为非零。写比较表达式(如 a > b)时直接当条件用。 |