# Wrong calculation in Tikz foreach

I've a misunderstanding about the method Tikz compute some numbers. I draw a graph with some scale. Here is a MWE :

\documentclass{standalone}
\usepackage[french]{babel}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}[yscale=0.1,xscale=25]
\draw[<->] (0.5,0) node[below right]{t} -- (0,0) -- (0,100) node[above left]{x(t)};

\foreach \t in {0, 0.08, ..., 0.48}{%
\draw (\t,1) -- (\t,-1) node[below]{\t};}
\end{tikzpicture}
\end{document}


I thought 0.08 x 5 = 0.40 and not 0.40001. And why the number 0.48 does not appear ?

I guess the xscale factor is not foreign by this problem but i can't address the problem by changing this factor. Otherwise i have a coefficient in all the following graphplots.

I read on this post that pgf has a uniform relative precision of about 4–5 correct digits. Is it the same for Tikz ? Is there a way to increase the precision of Tikz ?

Thx for you help !

The limited precision is the obstacle.

You can get much greater accuracy using expl3.

\documentclass{standalone}
\usepackage{tikz}
\usepackage{xparse}

\ExplSyntaxOn
\NewDocumentCommand{\fpforeach}{mmmm}
{% #1 = start, #2 = step, #3 = end, #4 = what to do
\fp_step_inline:nnnn { #1 } { #2 } { #3 } { #4 }
}
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}[yscale=0.1,xscale=25]
\draw[<->] (0.5,0) node[below right]{t} -- (0,0) -- (0,100) node[above left]{x(t)};

\fpforeach{0}{0.08}{0.48}
{
\draw (#1,1) -- (#1,-1) node[below]{#1};
}
\end{tikzpicture}

\end{document}


Beware of divisions, though, because the problems are still there and the final step might be missing due to accuracy issues nonetheless, but this is a problem with all floating point computations.

• Is it possible for you to explain what fp_step_inline:nnnn do ? I've never seen this command/function and the corresponding syntax untill now. – Piroooh Oct 11 '18 at 15:51
• @Piroooh It's expl3, the programming layer of the future LaTeX3. You can peruse the site finding several examples of how it works. – egreg Oct 11 '18 at 15:53

The Tikz manual states that this is normal, and I quote (p 902):

Normally, when a list item ... is encountered, there should already have been two list items before it, which where numbers. Examples of numbers are 1, -10, or -0.24. Let us call these numbers x and y and let d := y − x be their difference. Next, there should also be one number following the three dots, let us call this number z.

In this situation, the part of the list reading x,y,...,z is replaced by x, x + d, x + 2d, x + 3d, ..., x + md where the last dots are semantic dots, not syntactic dots. The value m is the largest number such that x + md ≤ z if d is positive or such that x + md ≥ z if d is negative.

Perhaps it is best to explain this by some examples: The following <list> have the same effects:

\foreach \x in {1,2,...,6} {\x, } yields 1, 2, 3, 4, 5, 6

\foreach \x in {1,2,3,...,6} {\x, } yields 1, 2, 3, 4, 5, 6

\foreach \x in {1,3,...,11} {\x, } yields 1, 3, 5, 7, 9, 11

\foreach \x in {1,3,...,10} {\x, } yields 1, 3, 5, 7, 9

\foreach \x in {0,0.1,...,0.5} {\x, } yields 0, 0.1, 0.20001, 0.30002, 0.40002

\foreach \x in {a,b,9,8,...,1,2,2.125,...,2.5} {\x, } yields a, b, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 2.125, 2.25, 2.375, 2.5

Like you, I asked myself the question and @egreg answered it excellently here: Why does pgffor estimate that 0.1-0=0.100005 in a \foreach loop?

• Very nice, in fact it's due to the decimal values and not the scale factor ! I read the p.675 in the pgf-tikz manual who is the same than what you have quoted and the answer of @egreg. A way is simply to erase the dots and to write the numbers one-by-one. Easy for 5 values, less convenient for a bigger sample. Thx to quote the Tikz manual and the corresponding topic ! – Piroooh Oct 11 '18 at 15:32
• Yes, and @RuixiZhang gives a way to keep the accuracy of calculations with a foreach loop in his answer here: tex.stackexchange.com/a/446027/138900 – AndréC Oct 11 '18 at 15:34

You can fix this by first working with integers and then reformatting the numbers to be the decimal representation you'd like to have:

First, I set the precision for the floating point

\pgfkeys{/pgf/number format/precision=2}


Then in the foreach loop I parse the integers to become the desired decimals using the following code

\pgfmathparse{\t/100}
\pgfmathroundtozerofill{\pgfmathresult}
\pgfmathsetmacro\t{\pgfmathresult}


Here's the full code:

\documentclass{standalone}
\usepackage[french]{babel}
\usepackage{tikz}

\begin{document}

\begin{tikzpicture}[yscale=0.1,xscale=25]
\draw[<->] (0.5,0) node[below right]{t} -- (0,0) -- (0,100) node[above left]{x(t)};

\pgfkeys{/pgf/number format/precision=2}
\foreach \t in {0, 8, ..., 48}
{
\pgfmathparse{\t/100}
\pgfmathroundtozerofill{\pgfmathresult}
\pgfmathsetmacro\t{\pgfmathresult}
\draw (\t,1) -- (\t,-1)
node[below]
{\t};
}
\end{tikzpicture}

\end{document}

• By this way, there is no risk Tikz make also rounded errors ? By divinding in pgfmathparse{\t/100} ? Or it is the goal to use \pgfmathroundtozerofill ? I'm not familiar with pgf. – Piroooh Oct 11 '18 at 15:54
• It's not that TikZ makes a rounding error so much as TeX underlying mechanism for doing arithmetic allows errors to gradually creep in if you're working with non-integer values (this will be true for any computer system). pgf is what underlies TikZ. The round to zero fill works with the designated precision to represent the decimal number with exactly two digits. – A.Ellett Oct 11 '18 at 16:56