4

I have a list of numbers from 1 to 12. I want to print the numbers 3,6,9 and 12 in purple, the others in blue. With my code:

\documentclass{standalone}
\usepackage{tikz,ifthen}

\begin{document}
    \begin{tikzpicture}
        \foreach \i in {1,...,12}{
                \ifthenelse {\i/3=int(\i/3)} {\draw[purple] (.75*\i,0) node ()  {\i};}{\draw[blue] (.75*\i,0) node ()  {\i};}   
        }
    \end{tikzpicture}   
\end{document}

I have errors and all numbers in blue. Why?

4 Answers 4

7

The ifthen package cannot evaluate expressions like \i/3 or int(\i/3) in a condition. You have to compute the integer expression first and then compare strings. You can use \numexpr and \number:

\documentclass[border=25pt]{standalone}
\usepackage{tikz,ifthen}

\begin{document}
\begin{tikzpicture}
  \foreach \i in {1,...,12}{%
    \ifthenelse{\equal{\number\i}{\number\numexpr\i/3*3\relax}}%
      {\draw[purple] (.75*\i,0) node {\i};}%
      {\draw[blue]   (.75*\i,0) node {\i};}%
  }
\end{tikzpicture}
\end{document}

Here \numexpr\i/3*3\relax computes (\i/3)*3 with integer division, and if it is equal to \i, then \i is divisible by 3.

enter image description here

Note that for this kind of task it is generally better to avoid ifthen altogether and use primitive numeric conditionals such as \ifnum instead. For example:

\documentclass[border=25pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
  \foreach \i in {1,...,12}{

    % compute \rest = \i mod 3
    \pgfmathtruncatemacro{\rest}{mod(\i,3)}

    \ifnum\rest=0
      \draw[purple] (.75*\i,0) node {\i};
    \else
      \draw[blue]   (.75*\i,0) node {\i};
    \fi
  }
\end{tikzpicture}
\end{document}
0
6

You can use pgfmath facilities or l3fp.

\documentclass{article}
\usepackage{tikz,ifthen}

\begin{document}

\begin{tikzpicture}
  \foreach \i in {1,...,12}{
    \pgfmathsetmacro\test{mod(\i,3)==0}
    \ifthenelse {\test=1}
      {\draw[purple] (.75*\i,0) node ()  {\i};}
      {\draw[blue] (.75*\i,0) node ()  {\i};}
  }
\end{tikzpicture}

\begin{tikzpicture}
  \foreach \i in {1,...,12}{
    \edef\test{\fpeval{\i/3==trunc(\i/3)}}
    \ifthenelse {\test=1}
      {\draw[purple] (.75*\i,0) node ()  {\i};}
      {\draw[blue] (.75*\i,0) node ()  {\i};}
  }
\end{tikzpicture}

\end{document}

output

Or you can use a reimplementation of \ifthenelse.

\documentclass{article}
\usepackage{tikz}

% https://tex.stackexchange.com/a/467527/4427
\ExplSyntaxOn
\NewExpandableDocumentCommand{\xifthenelse}{mmm}
 {
  \bool_if:nTF { #1 } { #2 } { #3 }
 }

\cs_new_eq:NN \numtest     \int_compare_p:n
\cs_new_eq:NN \oddtest     \int_if_odd_p:n
\cs_new_eq:NN \fptest      \fp_compare_p:n
\cs_new_eq:NN \dimtest     \dim_compare_p:n
\cs_new_eq:NN \deftest     \cs_if_exist_p:N
\cs_new_eq:NN \namedeftest \cs_if_exist_p:c
\cs_new_eq:NN \eqdeftest   \token_if_eq_meaning_p:NN
\cs_new_eq:NN \streqtest   \str_if_eq_p:ee
\cs_new_eq:NN \emptytest   \tl_if_empty_p:n
\cs_new_eq:NN \blanktest   \tl_if_blank_p:n
\cs_new_eq:NN \booleantest \legacy_if_p:n
\cs_new:Npn \modetest #1
 {
  \str_case:nnF { #1 }
   {
    {h}{\mode_if_horizontal_p:}
    {v}{\mode_if_vertical_p:}
    {m}{\mode_if_math_p:}
    {i}{\mode_if_inner_p:}
   }
   {\c_false_bool}
 }
\cs_new:Npn \enginetest #1
 {
  \str_case:nnF { #1 }
   {
    {luatex}{\sys_if_engine_luatex_p:}
    {pdftex}{\sys_if_engine_pdftex_p:}
    {ptex}{\sys_if_engine_ptex_p:}
    {uptex}{\sys_if_engine_uptex_p:}
    {xetex}{\sys_if_engine_xetex_p:}
   }
   {\c_false_bool}
 }
\ExplSyntaxOff


\begin{document}

\begin{tikzpicture}
  \foreach \i in {1,...,12}{
    \xifthenelse {\fptest{\i/3==trunc(\i/3)}}
      {\draw[purple] (.75*\i,0) node ()  {\i};}
      {\draw[blue] (.75*\i,0) node ()  {\i};}   
  }
\end{tikzpicture}   

\end{document}

For the \xifthenelse version, you can also add a user level function for the modulo operation: add

\cs_new_eq:NN \IntMod \int_mod:nn

just before \ExplSyntaxOff and the test can become

\xifthenelse{\numtest{\IntMod{\i}{3}==0}}
5

Consider using \fpeval{} rather than pgfmath if you do not need compatibility with old releases of LaTeX. This is faster, more accurate and significantly less likely to result in the too-large errors which are the bane of pgfmath users' existence.

\fpeval{} is a 2e interface to the l3fp programming module. Although it slightly oddly lacks a mod function, it does have trunc, which provides a reasonable alternative.

As far as I know, there is no 2e interface to the programming layer's if <compare fps> then <something> else <something else>, so \ifnum remains the best option here, but we can use \fpeval to compare the expressions and insert 1 or 0 into the input stream. Then we only need \ifnum<result>=1 ... \else ... \fi, which isn't at risk of exceeding any TeX limitation.

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
  \foreach \i in {1,...,12}{
    \ifnum\fpeval{(\i/3)=(trunc(\i/3)) ? 1 : 0}=1
      \draw[purple] (.75*\i,0) node ()  {\i};
    \else
      \draw[blue] (.75*\i,0) node ()  {\i};
    \fi
  }
\end{tikzpicture}   
\end{document}

result with fpeval

1

You can use \ifnum TeX primitive, no \ifthenelse macro is needed. Your example looks like this:

\begin{tikzpicture}
  \foreach \i in {1,...,12}{%
    \ifnum \i=\numexpr\i/3*3\relax
      \draw[purple] (.75*\i,0) node {\i};\else
      \draw[blue]   (.75*\i,0) node {\i};\fi
  }
\end{tikzpicture}
1
  • Simplest solution. Thanks Commented 8 hours ago

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.