15

I'am using a macro from here (thanks to Schrödinger's cat). See my MWE:

\documentclass{scrartcl}
\usepackage{tikz}
\usetikzlibrary{fpu}
\newcommand\pgfmathparseFPU[1]{
                               \begingroup
                                 \pgfkeys{
                                          /pgf/fpu,
                                          /pgf/fpu/output format = fixed
                                         }
                                 \pgfmathparse{#1}
                                 \pgfmathsmuggle
                                 \pgfmathresult
                               \endgroup}

\begin{document}

  %data values:
  \def\UABmValues{{14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1}}

  %prints the result to the console:
  \foreach[count = \i from 0] \k in {30, 35, ..., 80}
    {
     \pgfmathsetmacro{\UABmValues}{\UABmValues[\i]}
     \pgfmathparseFPU{-25500 / (\UABmValues / 1000 - 255 / 52) - 5200 - 3.0897 / 8 * \k}\i, \pgfmathresult\\
    }

\end{document}

Gives:

  1. 4.414001000000000
  2. 3.483002000000000
  3. 3.652002000000000
  4. 2.221002000000000
  5. 0.990002
  6. 0.159003
  7. -0.571997
  8. -1.302997000000000
  9. -1.033997000000000
  10. -0.064996
  11. 1.304004000000000

When I do the same, let say, with MATLAB:

    UABmValues = [14.9 15.8 17.7 18.3 19 20 21.1 22.2 24.3 26.9 30.1];
    R = 30 : 5 : 80;

    %prints the result to the console:
    for j = 1 : 11

      result = -25500 / (UABmValues(j) / 1000 - 255 / 52) - 5200 - 3.0897 / 8 * R(j);
      fprintf('j=%d, ', j)
      fprintf('%d.\n', result)

    end

Than I get following:

  1. 4.261621e+00.
  2. 3.290914e+00.
  3. 3.388431e+00.
  4. 2.098301e+00.
  5. 9.151911e-01.
  6. 5.300458e-02.
  7. -7.017887e-01.
  8. -1.456052e+00.
  9. -1.139024e+00.
  10. -2.840543e-01.
  11. 1.217927e+00.

The difference is huge.

Why is it so? Any suggestions how to solve it with fpu, if at least possible?

Thank you for your help and effort in advance!

Su-47
  • 2,508
  • 7
    The PGF FPU uses TeX \dimen registers for calculations, so it has the same accuracy restrictions. The smallest representable difference in a TeX \dimen is 1sp, which is 0.00002pt (try \the\dimexpr1sp\relax). If you need more accuracy, try the LaTeX3 FPU (loaded by the xfp package). – Phelype Oleinik Dec 26 '19 at 12:32
  • 1
    @PhelypeOleinik fp gives good results ... but I agree with you xfp seems to be the good way. Perhaps lua is the better way ? – Alain Matthes Dec 26 '19 at 13:15
  • 5
    @AlainMatthes Yes, fp has a higher accuracy than the LaTeX3 FPU. (The latter conforms to the IEEE-754 standard, accurate to 16 significant digits or so). But xfp (and Lua, for that matter) is fully expandable, while fp is not. I'm not sure about Lua's accuracy. But my job description is to advertise expl3, so I had to suggest that ;-) – Phelype Oleinik Dec 26 '19 at 13:19
  • 1
    @PhelypeOleinik I agree with you xfp is fully expandable. I use fp because it was the only solution several years ago.I think you have wit lua IEEE 754 double precision floating point – Alain Matthes Dec 26 '19 at 14:42

3 Answers3

20

The PGF floating point module is inaccurate, as it uses TeX arithmetic, so it doesn't go beyond five decimal digits. It is not meant as an all-purpose floating point arithmetic tool, but just to do typesetting.

Use xfp.

\documentclass{article}
\usepackage{tikz}
\usepackage{xfp}

\begin{document}

%data values:
\def\UABmValues{{14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1}}

%prints the result to the console:
\foreach[count = \i from 0] \k in {30, 35, ..., 80}
  {
   \pgfmathsetmacro{\UABmValues}{\UABmValues[\i]}
   \i, $\fpeval{-25500 / (\UABmValues / 1000 - 255 / 52) - 5200 - 3.0897 / 8 * \k}$\par
  }

\end{document}

enter image description here

egreg
  • 1,121,712
13

You can try fp, xfp (see egreg's answer) or lua

1) update : version with lua

% !TEX TS-program = lualatex

\documentclass{scrartcl}
\usepackage{pgffor,pgfmath}
\def\luafun#1#2{
    \directlua{
        x = #1;
        y = #2;
       r=-25500/(x/1000-255/52)-5200-3.0897/8*y
       tex.print(r)}
} 

\begin{document}
\def\UABmValues{{14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1}}

\foreach[count = \i from 0] \k in {30, 35, ..., 80}
{
\pgfmathsetmacro{\myval}{\UABmValues[\i]}%
\luafun{\myval}{\k}\par
 }

\end{document}

enter image description here

2) old version with fp

\documentclass{scrartcl}
\usepackage{tikz,fp}
\newcommand\pgfmathparseFP[1]{
   \begingroup
        \FPeval\pgfmathresult{(#1)}
     \pgfmathsmuggle
     \pgfmathresult
   \endgroup
    }

\begin{document}

  %data values:
\def\UABmValues{{14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1}}

%prints the result to the console:
\foreach[count = \i from 0] \k in {30, 35, ..., 80}
{
\pgfmathsetmacro{\myval}{\UABmValues[\i]}%
\pgfmathparseFP{-25500/(\myval/1000-255/52)-5200-3.0897/8*\k}\i, \pgfmathresult\par
 }

\end{document}

enter image description here

Alain Matthes
  • 95,075
6

An implementation with the CAS Sage(math) and SageTeX:

enter image description here

I use arara: sagetex for compiling.

% arara: pdflatex
% arara: sagetex
% arara: pdflatex

\documentclass{scrartcl}
\usepackage{sagetex, amsmath}
\usepackage{tikz}
\usetikzlibrary{fpu}
\newcommand\pgfmathparseFPU[1]{
\begingroup
\pgfkeys{
 /pgf/fpu,
/pgf/fpu/output format = fixed
}
\pgfmathparse{#1}
\pgfmathsmuggle
\pgfmathresult
\endgroup}

\begin{document}
%data values:
\def\UABmValues{{14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1}}

\section{pgfmath}
\foreach[count = \i from 0] \k in {30, 35, ..., 80}
{
\pgfmathsetmacro{\UABmValues}{\UABmValues[\i]}
\pgfmathparseFPU{-25500 / (\UABmValues / 1000 - 255 / 52) - 5200 - 3.0897 / 8 * \k}\noindent\i, \UABmValues, \pgfmathresult \\
}

\section{SageTeX}
\subsection{Sage-Output}
$\sagestr{MyOut}$

\subsection{From sageblock or sagesilent}
\begin{sageblock}
Val = ([14.9, 15.8, 17.7, 18.3, 19, 20, 21.1, 22.2, 24.3, 26.9, 30.1])
## Test:
#print Val[1]
#print len(Val)

# Function
f(x,y) = -25500/(x/1000 - 255/52) -5200 -3.0897/8 *(30+5*y)

# Short Output
#for i in range (len(Val)): print i,',',float(Val[i]),',', f(Val[i],i)

# Better Output    
data = [(i,  float(Val[i]), f(Val[i],i)) for i in range(len(Val))] 
data_str = [',   '.join(map(str, t)) for t in data] 
data_str = '\n'.join(data_str) 

MyOut = latex(data_str)
#print data_str
\end{sageblock}
\end{document}
cis
  • 8,073
  • 1
  • 16
  • 45