¿Existe una forma sencilla de mejorar la precisión de pgfmath para funciones trigonométricas?

¿Existe una forma sencilla de mejorar la precisión de pgfmath para funciones trigonométricas?

Quería crear una tabla de valores trigonométricos usando pgfmath. Sin embargo, la precisión está un poco fuera de lugar. ¿Hay alguna manera de mejorar esto internamente TikZ?

Esto está relacionado con una pregunta similar que acabo de publicar:¿Hay alguna manera de rellenar ceros hasta el final de un número redondeado con Expl3?

Aquí está mi ejemplo de trabajo actual:

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{calc,fixedpointarithmetic}

\def\mynum{0}
\def\myvoffset{0pt}

\usepackage[margin=0.5in]{geometry}

\begin{document}

Using \texttt{TikZ}

\begin{tikzpicture}[/pgf/number format/.cd,fixed,precision=4,verbatim]

  \coordinate(UL) at (0,0);

  \node at (UL) {Degrees};
  \node[anchor=west] at ($(UL.west)+(1cm,0)$) {$\sin$};
  \node[anchor=west] at ($(UL.west)+(2.75cm,0)$) {$\cos$};
  \node[anchor=west] at ($(UL.west)+(4.50cm,0)$) {$\tan$};

  \foreach \myn in {1,2,3,...,45}
  {
    \pgfmathparse{int(mod(\myn-1,5))}
    \ifnum\pgfmathresult=0\relax
      \xdef\myvoffset{\dimexpr\myvoffset+1.350\baselineskip}%%
    \else
      \xdef\myvoffset{\dimexpr\myvoffset+1.00\baselineskip}%%
    \fi

    \coordinate (DEG/\myn)   at ($(UL.west)-(0,\myvoffset)$);
    \coordinate (DEG/S/\myn) at ($(DEG/\myn)+(1cm,0)$);
    \coordinate (DEG/C/\myn) at ($(DEG/S/\myn)+(1.75cm,0)$);
    \coordinate (DEG/T/\myn) at ($(DEG/C/\myn)+(1.75cm,0)$);

    \node[anchor=east] at (DEG/\myn) {$\myn^\circ$};
    \pgfmathparse{sin(\myn)} \node[anchor=west] at (DEG/S/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};
    \pgfmathparse{cos(\myn)} \node[anchor=west] at (DEG/C/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};
    \pgfmathparse{tan(\myn)} \node[anchor=west] at (DEG/T/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};

  }

\end{tikzpicture}

\end{document}

ingrese la descripción de la imagen aquí

Respuesta1

No lo sé con pgfmath; con expl3puedes compilar tu tabla de esta manera:

\documentclass{article}
\usepackage[margin=1cm]{geometry}

\usepackage{array,siunitx}

\sisetup{
  add-decimal-zero,
  round-precision=5,
  round-mode=places,
  round-integer-to-decimal,
  group-digits=false,
  detect-all,
}

\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\trigtable}{ }
 {
  \__aellett_do_trig:
  \begin{tabular}{r *{3}{ >{\ttfamily}r }}
  & \multicolumn{1}{c}{$\sin$}
  & \multicolumn{1}{c}{$\cos$}
  & \multicolumn{1}{c}{$\tan$}
  \\
  \tl_use:N \l__aellett_body_tl
  \end{tabular}
 }

\tl_new:N \l__aellett_body_tl

\cs_new:Npn \aellett_compute:nn #1 #2
 {
  \num { \fp_to_decimal:n { \fp_eval:n { round ( #1(#2) , 5 ) } } }
 }

\cs_new_protected:Npn \__aellett_do_trig:
 {
  \tl_clear:N \l__aellett_body_tl
  \int_step_inline:nnnn { 1 } { 1 } { 89 }
   {
    \tl_put_right:Nn \l__aellett_body_tl { $##1^\circ$ & }
    \tl_put_right:Nx \l__aellett_body_tl
     { 
      \aellett_compute:nn { sind } { ##1 } &
      \aellett_compute:nn { cosd } { ##1 } &
      \aellett_compute:nn { tand } { ##1 } 
     }
    \int_compare:nTF { \int_mod:nn { ##1 } { 5 } == 0 }
     {
      \tl_put_right:Nn \l__aellett_body_tl { \\[1ex] }
     }
     {
      \tl_put_right:Nn \l__aellett_body_tl { \\ }
     }
   }
  % 90 degrees
  \tl_put_right:Nx \l__aellett_body_tl
   {
    $90^\circ$ &
    \aellett_compute:nn { sind } { 90 } &
    \aellett_compute:nn { cosd } { 90 } &
    --- 
   }

 }

\ExplSyntaxOff

\begin{document}
\tiny
\trigtable

\end{document}

Aquí está el comienzo:

comenzar

Y aquí está el final, sólo para mostrar lo que sucede a 89 grados:

fin

Utilicé cinco dígitos para comparar con los valores bcdevueltos por la tangente de 89 grados:

57.28996163075942465214

Respuesta2

Amplíe sus opciones con fixed zerofill.

\documentclass{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{calc,fixedpointarithmetic}
\def\mynum{0}
\def\myvoffset{0pt}
\usepackage[margin=0.5in]{geometry}

\begin{document}
%Using \texttt{TikZ}
\begin{tikzpicture}[/pgf/number format/.cd,fixed,precision=4,verbatim, fixed zerofill]
  \coordinate(UL) at (0,0);
  \node at (UL) {Degrees};
  \node[anchor=west] at ($(UL.west)+(1cm,0)$) {$\sin$};
  \node[anchor=west] at ($(UL.west)+(2.75cm,0)$) {$\cos$};
  \node[anchor=west] at ($(UL.west)+(4.50cm,0)$) {$\tan$};
  \foreach \myn in {1,2,3,...,45}
  {
    \pgfmathparse{int(mod(\myn-1,5))}
    \ifnum\pgfmathresult=0\relax
      \xdef\myvoffset{\dimexpr\myvoffset+1.350\baselineskip}%%
    \else
      \xdef\myvoffset{\dimexpr\myvoffset+1.00\baselineskip}%%
    \fi
    \coordinate (DEG/\myn)   at ($(UL.west)-(0,\myvoffset)$);
    \coordinate (DEG/S/\myn) at ($(DEG/\myn)+(1cm,0)$);
    \coordinate (DEG/C/\myn) at ($(DEG/S/\myn)+(1.75cm,0)$);
    \coordinate (DEG/T/\myn) at ($(DEG/C/\myn)+(1.75cm,0)$);
    \node[anchor=east] at (DEG/\myn) {$\myn^\circ$};
    \pgfmathparse{sin(\myn)} \node[anchor=west] at (DEG/S/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};
    \pgfmathparse{cos(\myn)} \node[anchor=west] at (DEG/C/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};
    \pgfmathparse{tan(\myn)} \node[anchor=west] at (DEG/T/\myn) {\texttt{\pgfmathprintnumber{\pgfmathresult}}};
  }
\end{tikzpicture}
\end{document}

mwe

Respuesta3

Con la aritmética estándar de TeX, la precisión es muy limitada. Si necesitas resultados más precisos, es posible que necesites utilizar algún programa externo o cualquier extensión de TeX, como luatex.

Usando mi paquetecalculadoraObtengo resultados similares a los que obtienes con Tikz:

\documentclass{article}
\usepackage{calculator}
\usepackage{ifthen}

\begin{document}
\newcounter{angle}
\newcommand{\trigfunctions}[1]{%
    #1^{\mathrm{o}} &
    \DEGREESSIN{#1}{\sine}
    \ROUND[4]{\sine}{\sine}
    \sine & 
    \DEGREESCOS{#1}{\cosine}
    \ROUND[4]{\cosine}{\cosine}
    \cosine  & 
    \DEGREESTAN{#1}{\tangent}
    \ROUND[4]{\tangent}{\tangent}
    \tangent& 
    \DEGREESCOT{#1}{\cotangent}
    \ROUND[4]{\cotangent}{\cotangent}
    \cotangent \\}

\small
\[
\begin{array}{*{5}{r}}
\multicolumn{1}{c}{\alpha} & \multicolumn{1}{c}{\sin\alpha} & 
                             \multicolumn{1}{c}{\cos \alpha} & 
                             \multicolumn{1}{c}{\tan\alpha} & 
                             \multicolumn{1}{c}{\cot\alpha} \\
\whiledo{\value{angle}<45}{\stepcounter{angle}\trigfunctions{\theangle}}
\end{array}
\]
\end{document}

tabla trigonométrica

información relacionada