Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

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}
share|improve this question
1  
Extract from pgfmanual: "The FPU’s relative precision is at least 1·10^−4 although operations like addition have a relative precision of 1·10^−6". So, no trick to increase relative precision. –  Paul Gaborit Sep 29 '13 at 7:33

2 Answers 2

up vote 4 down vote accepted

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

share|improve this answer

Exact or arbitrarily precise computations with fractions are possible with package xintfrac, and made easier with \xintexpr ... \relax provided by package xintexpr (which loads xintfrac). See xint bundle.

So here we use the round(x,10) function inside xinttheexpr...\relax to define a macro \tmp by an \edef to be the fraction rounded to 10 digits after the decimal mark.

Note though that apart from sqrt only addition, multiplication, division, subtraction, and powers with integral exponents are possible.

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{fpu}
\usepackage{xintexpr} % http://ctan.org/pkg/xint

\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}};

  % third test (xintexpr)
  \edef\tmp{\xinttheexpr round(\i/(\nu-1),10)\relax}
  \pgfkeys{/pgf/fpu=false}
  \draw[blue] (\xi,-2.1cm)
           -- (\xi, -3.2cm) 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}

use of xint

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.