[Tex/LaTex] Increasing precision in \pgfmathsetmacro

pgfmathtikz-pgf

I would like to use

\pgfmathprintnumber[/pgf/number format/frac]{\var}

where \var is a variable set by \pgfmathsetmacro and I'm having similar difficulties as in this and this question. I'm aware that the frac format is numerically unstable.

My problem is that the precision of \pgfmathsetmacro seems to be five digits, but for the following minimal example I'd need seven digits. Is there a trick to do it?


EDIT:

The following solutions are possible (I haven't decided which one is the best.. please vote!)

  • Package xintexpr and round(x,10) to have precision 10 result (by @jfbu)
    • changes just the division
  • frac shift=2 (by @Qrrbrbirlbel)
    • simple addition
    • no additional packages
  • fixed point arithmetic of tikz to calculate a more precise result (also by @Qrrbrbirlbel)
    • newcommand, but otherwise also just changes the division

Original post continued
See this example:

  • blue my first attempt
  • black with fpu
  • red: what I want.

enter image description here

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fpu}
\usepackage{fp} % uncommenting results in the following warning, but no change in output
%! Package pgf /pgf/number format/frac warning=true: /pgf/number format/frac of
%`3.3333e-1' = 100009 / 300030 might be large due to instabilities. Try \usepack
%age{fp} to improve accuracy.

\begin{document}
\begin{tikzpicture}
\def\nu{4}
\def\w{5}
\pgfmathsetmacro{\nn}{\nu-1}
\foreach \i in {0,1,...,\nn}{
  \pgfmathsetmacro{\xi}{\i*\w/(\nu-1)}
  % first test
  \pgfmathsetmacro{\xival}{\i/(\nu-1)}
  \draw[blue] (\xi, -1.1 cm) -- (\xi,2pt)  node[above,align=center] 
     {\pgfmathprintnumber[fixed, precision=10]{\xival} \\ 
     \pgfmathprintnumber[/pgf/number format/frac]{\xival}};

  % second test (fpu)
  \pgfkeys{/pgf/fpu}
  \pgfmathparse{\i/(\nu-1)}
  \edef\tmp{\pgfmathresult}
  \pgfkeys{/pgf/fpu=false}
  \draw (\xi,2pt) -- (\xi, -1.1 cm) node[below,align=center] 
      {\pgfmathprintnumber[fixed, precision=10]{\tmp} \\ 
      \pgfmathprintnumber[/pgf/number format/frac]{\tmp}};
  } % end foreach

% this works (two digits '3' added)
\node[red] at (1,-.5) {\pgfmathprintnumber[/pgf/number format/frac]{0.3333333}};

\end{tikzpicture}
\end{document}

Best Answer

The 0.33333 is simply too imprecise for the high precision that /frac and fp offers as 100009/300030 (which is 0.3¯33330000) is nearer to 0.33333 than to 1/3.

You can work around this by giving the option /pgf/number format/frac shift=2 (initially 4) or by using fp also for the division.

Code

\documentclass{standalone}
\usepackage{fp,tikz}
\usetikzlibrary{fpu,fixedpointarithmetic}
\newcommand*{\pgfMathsetmacro}[2]{\pgfmathparse{#2}\let#1\pgfmathresult}
\begin{document}
\begin{tikzpicture}[x=1.5cm]
\def\nu{4} \def\w{5}
\foreach \i in {0,1,...,\the\numexpr\nu-1}{
  \pgfmathsetmacro\xival{\i/(\nu-1)}
  \draw (\i,0pt) node[above,align=center] 
    {{\tiny\pgfmathprintnumber[fixed, precision=10]{\xival}} \\ 
           \pgfmathprintnumber[/pgf/number format/.cd, frac, frac shift=2]{\xival}};

  \tikzset{fixed point arithmetic}
  \pgfMathsetmacro\xival{\i/(\nu-1)}
  \draw (\i,-1) node[above,align=center] 
    {{\tiny\pgfmathprintnumber[fixed, precision=10]{\xival}} \\ 
           \pgfmathprintnumber[/pgf/number format/frac]{\xival}};
}
\end{tikzpicture}
\end{document}

Output

enter image description here