Calcul avec LaTeX

Bonjour à tous,
n'ayant pas trouvé de sujet sur "pgfmath" sur le forum, je me permets de poser ma question ici.
J'aurais voulu savoir si quelqu'un peut m'expliquer la différence entre pgfmathparse et fpeval car les quelques lignes de code ci-dessous ne donnent pas le même résultat (et je ne pense pas avoir fait une erreur dans la syntaxe :-) )
\documentclass[10pt,a4paper]{letter}
\usepackage[utf8]{inputenc}
\usepackage[french]{babel}
\usepackage[T1]{fontenc}
\usepackage{tikz}
\usepackage{xfp}
\usepackage{fp}
\usepackage{pgfmath}
\begin{document}

$(1.01)^{365}{\pgfmathparse{1.01^365}={\pgfmathresult}}$\\

$(1.01)^{365}{\pgfmathparse{pow(1.01,365)}={\pgfmathresult}}$\\

$(1.01)^{365}=\fpeval{(1.01)^365}$

\end{document}
qui donne comme résultats :
(1.01) ^365 = 37.6006
(1.01) ^365 = 37.6006
(1.01) ^365 = 37.78343433288716

Comment peut-on expliquer cette différence ?

Je remercie d'avance la ou les bonne(s) âme(s) qui prendra(ont) quelques moments de son (leur) dimanche pour éclairer ma lanterne.
Meilleures salutations à tous.
Fabrice

Réponses

  • Bonjour,

    J'écrirais ça comme ceci (pas besoin de \usepackage{tikz} ; pas besoin de \usepackage{fp}, c'est une troisième implémentation de FPU ; pas de \\ en fin de paragraphe ; ne pas abuser des accolades en mode maths) :
    \documentclass{article}
    \usepackage{xfp}
    \usepackage{pgfmath}
    \begin{document}
    
    $1.01^{365} = \pgfmathparse{1.01^365} \pgfmathresult$
    
    $1.01^{365} = \pgfmathparse{pow(1.01,365)} \pgfmathresult$
    
    $1.01^{365} = \fpeval{(1.01)^365}$
    
    \end{document}
    
    pgfmath supporte plusieurs implémentations de FPU pour réaliser les calculs. Par défaut et aussi avec \usetikzlibrary{fpu} (qui doit être activée sinon ça ne fait rien ; ton code ne l'utilise pas), le nombre de chiffres significatifs est faible car pour calculer vite, le code s'appuie sur les dimen registers de TeX (le manuel de PGF & TikZ donne un nombre de chiffres significatifs d'environ 4 ou 5 avec \usetikzlibrary{fpu}). \usetikzlibrary{fpu} permet de représenter des nombres de très grande ou très petite valeur absolue car il utilise un exposant en plus de la mantisse :
    The FPU supports at least the complete IEEE double precision number range
    C'est la principale différence avec la FPU de pgfmath par défaut. Il y a aussi une FPU qui calcule en virgule fixe pour pgfmath. Ces trois FPU de pgfmath sont interchangeables : on peut utiliser les mêmes expressions dans \pgfmathparse{...}, quelle que soit la FPU qu'il y a sous le capot (sauf pour certaines opérations non supportées par certaines FPU). Mais il faut faire attention en sortie : les nombres ne sont pas représentés de la même manière dans \pgfmathresult selon la FPU pgfmath utilisée. C'est ça qui est un peu délicat quand on fait ces changements au milieu de code TikZ ou pgfplots.

    xfp est une interface LaTeX2e pour l3fp, lequel est documenté avec 'texdoc interface3' et 'texdoc source3'. Les flottants sont a priori conformes à la norme IEEE-754-2008. On a droit à $\pm m \cdot 10^{n}$ avec $1\leqslant m \leqslant 10^{16}$ et $-10000 \leqslant n \leqslant 10000$. Il y a aussi des NaN, $\pm 0$, $\pm \infty$ (\usetikzlibrary{fpu} de pgfmath a aussi ces choses-là). xfp est donc notamment plus précis que pgfmath standard et pgfmath + \usetikzlibrary{fpu} au niveau du nombre de chiffres significatifs, et l'étendue est très importante (c'est moi qui appelle ça l'étendue). De plus, l'interface est fully expandable, contrairement à \pgfmathparse. Bref, c'est le top sauf si on a besoin d'un truc assez particulier genre calcul en virgule fixe.

    D'un autre côté, LuaTeX peut calculer précisément avec l'unité de calcul de l'interpréteur Lua. marsup a posté un exemple utilisant cette technique il y a un petit moment.
  • Je précise que l'aspect fully expandable (= développable) de la macro \fpeval du package xfp permet de l'utiliser dans n'importe quel contexte où l'argument (plus généralement, la liste de lexèmes contenant \fpeval{...}) est développé récursivement. Par exemple, dans le deuxième argument de \setlength ou dans l'argument de \pgfmathparse ou l'un de ses avatars (\pgfmathsetmacro, \pgfmathtruncatemacro, \pgfmathsetlength, \pgfmathsetlengthmacro, etc.) :
    \setlength{\unelongueur}{...\fpeval{...}...}
    
    ou
    \pgfmathparse{...\fpeval{...}...}
    
    Voic un exemple complet pour chacun de ces cas d'utilisation. Dans ce cas particulier, on pourrait bien sûr faire l'équivalent du 'max' avec le package eqparbox ou bien utiliser un tabular, mais évidemment, le \fpeval{...} pourrait contenir une expression mathématique bien plus compliquée.

    1) Dans le deuxième argument de \setlength :
    \documentclass{article}
    \usepackage{xfp}
    
    \newlength{\malongueur}
    \newlength{\malongueurA}
    \newlength{\malongueurB}
    
    \begin{document}
    
    \settowidth{\malongueurA}{Bla bla}
    \settowidth{\malongueurB}{Autre texte}
    \setlength{\malongueur}{\fpeval{max(\malongueurA, \malongueurB)}pt}
    
    \noindent
    \makebox[\malongueur][r]{Bla bla}\\
    \makebox[\malongueur][r]{Autre texte}
    
    \end{document}
    
    2) Dans l'argument de \pgfmathparse ou l'un de ses avatars (ici, \pgfmathsetlength) :
    \documentclass{article}
    \usepackage{xfp}
    \usepackage{pgfmath}
    
    \newlength{\malongueur}
    \newlength{\malongueurA}
    \newlength{\malongueurB}
    
    \begin{document}
    
    \settowidth{\malongueurA}{Bla bla}
    \settowidth{\malongueurB}{Autre texte}
    \pgfmathsetlength{\malongueur}{\fpeval{max(\malongueurA, \malongueurB)}pt}
    
    \noindent
    \makebox[\malongueur][r]{Bla bla}\\
    \makebox[\malongueur][r]{Autre texte}
    
    \end{document}
    

    Rien à voir : il peut être utile de noter que les fonctions circulaires (sinus, cosinus, etc.) prennent leur argument en radians avec xfp alors qu'il est par défaut interprété comme une mesure en degrés avec pgfmath.103818
Connectez-vous ou Inscrivez-vous pour répondre.