How to Use \pgfmathsetmacro in a TikZ \foreach Loop
At a glance
- 1. Check the loop body
Put every command that uses the loop variable inside the foreach body’s braces.
- 2. Calculate within the loop
Pass a macro and a valid numeric expression to pgfmathsetmacro.
- 3. Save values if needed
Loop-local definitions may disappear after an iteration; explicitly preserve a value used later.
A \pgfmathsetmacro calculation can be made directly inside a TikZ \foreach loop. The usual problems are scope—trying to use a value after the iteration that defined it—or loop syntax, such as leaving a command outside the loop body.
The example below calculates a square and uses it during each iteration. It also shows how to keep the final result for use after the loop.
A working example
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\foreach \n in {1,...,4} {
\pgfmathsetmacro{\sqval}{\n*\n}
\fill (\n,\sqval) circle (2pt);
\node[above] at (\n,\sqval) {$\sqval$};
\xdef\lastsquare{\sqval}
}
\end{tikzpicture}
The last square is \lastsquare.
\end{document}
In each pass, \n is the current loop value, and \pgfmathsetmacro{\sqval}{\n*\n} evaluates its square. The resulting macro can be used immediately in the loop body—for example, as a coordinate. The \xdef line saves the expanded value globally, so \lastsquare is still available after the loop. Here its value is 16.
The example needs only the tikz package. The \foreach command is provided by PGF/TikZ, and \pgfmathsetmacro is part of PGF’s math facilities.
The command’s basic form
Use this syntax:
\pgfmathsetmacro{\result}{expression}
The first argument must be a control sequence—the macro to receive the calculated number. The second argument is a PGF math expression. For example:
\pgfmathsetmacro{\result}{3*\n+1}
The expression can use the current loop variable. For a numeric list, a simple loop looks like this:
\foreach \n in {1,2,3} {
\pgfmathsetmacro{\result}{3*\n+1}
\node at (\n,0) {\result};
}
Each iteration calculates a new value of \result and uses it before moving on.
Why a result may vanish after the loop
A \foreach loop processes its body in a local group for each iteration. As a result, definitions made there are generally not available outside that iteration. This is useful: the same temporary macro can be recalculated on every pass without leaving unwanted definitions behind.
If you need one value afterward, make a global copy inside the loop. In the first example, \xdef\lastsquare{\sqval} expands \sqval and saves its current numeric value. Since it runs on every pass, the saved macro ends up holding the value from the final pass.
Use this sparingly. If the value is only needed to draw or label something in the loop, use it there instead of making it global. For more complicated data that must be retained across iterations, a list or another explicit data structure may be clearer than repeatedly overwriting one macro.
Common mistakes
- Leaving commands outside the loop body. When an iteration needs multiple commands, enclose all of them in braces after the loop’s list. Otherwise a command may run only once or may not have access to the intended loop variable.
- Using the result after its scope ends. A macro calculated in an iteration is intended for use in that iteration. Preserve it explicitly if later code needs it.
- Passing the wrong first argument. Write
\pgfmathsetmacro{\result}{...}, not\pgfmathsetmacro{result}{...}. The first argument is the macro name, including its backslash. - Putting non-numeric text in the expression. PGF math expects a valid expression. If your loop list contains labels such as
redorblue, use those as text; they are not numeric inputs to arithmetic. - Confusing calculation with formatting.
\pgfmathsetmacrostores a numeric result, not a formatted label with units. Add units or other text separately when typesetting the result.
If it still fails
Check the exact error and isolate the calculation. First, keep only the loop and a \pgfmathsetmacro line; then add the drawing or typesetting command back. Verify that the expression works with the current loop values and that every command that refers to the loop variable is inside the loop’s braces. If the error is about an undefined control sequence, also confirm that TikZ is loaded with \usepackage{tikz}.
References
Spotted an error? Send a correction. Read how we write and check articles in our editorial policy.