使用 tikz \pgfmathprintnumber 将数字格式化为 pi 的分数

使用 tikz \pgfmathprintnumber 将数字格式化为 pi 的分数

我希望能够自动输出类似\frac{\pi}{2}输入数字的内容.5*pi

我使用过number printingtikz 的一些宏(与库紧密相关fpu,至少在 cvs 版本中可用)。

我的想法是将数字除以pi,然后使用number format/frac,然后将 添加\pi到结果中。但由于出现舍入误差,它无法按预期工作。以下是2*pi1.5*pi和 的结果0.5*pi

三角标签

这是我目前所做的。

\documentclass{standalone}
\usepackage{tikz,fp}
\usetikzlibrary{fpu}
\makeatletter

% Adapted from the file /generic/pgf/math/pgfmathfloat.code.tex
\pgfkeys{%
  /pgf/number format/.cd,
  pi/.code = \pgfmath@set@number@printer{pgfmathprintnumber@pi}}

\def\pgfmathprintnumber@pi#1{%
  \pgfmathparse{#1/3.141592654}
  \pgfmathfloatparsenumber{\pgfmathresult}%
  \pgfmathfloatgetfrac{\pgfmathresult}%
  \expandafter\pgfmathprintnumber@pi@formatresult\pgfmathresult}

% Nothing really new here, just a copy of
% \pgfmathprintnumber@frac@formatresult only altered to add
% \pi to the result
\def\pgfmathprintnumber@pi@formatresult#1#2#3{%
  \begingroup
    \pgfkeysgetvalue{/pgf/number format/frac TeX}\pgfmathresult
    \toks0=\expandafter{\pgfmathresult}%
    \def\pgfmathfloat@loc@TMPa{#1}%
    \ifx\pgfmathfloat@loc@TMPa\pgfutil@empty
      \ifpgfmathprintnumber@showpositive
        \def\pgfmathfloat@loc@TMPa{+}%
      \fi
    \else
      \ifx\pgfmathfloat@loc@TMPa-%
      \else
        \ifx\pgfmathfloat@loc@TMPa+%
        \else
          \ifpgfmathprintnumber@showpositive
            \edef\pgfmathfloat@loc@TMPa{+\pgfmathfloat@loc@TMPa}%
          \fi
          \def\pgfmathfloat@loc@TMPb{%
            \pgfkeysvalueof{/pgf/number format/frac whole format/.@cmd}}%
          \expandafter\pgfmathfloat@loc@TMPb\pgfmathfloat@loc@TMPa\pgfeov
          \let\pgfmathfloat@loc@TMPa=\pgfmathresult
        \fi
      \fi
    \fi
    \toks1=\expandafter{\pgfmathfloat@loc@TMPa}%
    \edef\pgfmathresult{%
      \the\toks1 \ifnum#2=0 \else\the\toks0 {#2}{#3}\fi \pi}%
    \pgfmath@smuggleone\pgfmathresult
  \endgroup
}

\begin{document}

\pgfkeys{/pgf/number format/pi}

\pgfmathprintnumber{2*pi}

\pgfmathprintnumber{1.5*pi}

\pgfmathprintnumber{0.25*pi}

\end{document}

答案1

这是十进制到分数转换器的常见问题。以下是非 TikZ 解决方案,说明了这个问题:

在此处输入图片描述

该算法是迭代的,可以找到不同精度的解决方案,例如在上面的扫描中,您可以看到“正确解决方案”是第 3 行。但情况并非总是如此,例如,想想如何以0.313分数形式表示小数,可以是任何东西,具体5/16 -> 641/2048取决于您想要达到的精度。

\documentclass{article}
\usepackage{amsmath,fp}
\begin{document}
\makeatletter
\count@=1
\def\DecimalToFraction#1{
%helper macro
\FPset\zero{0}
\FPset\X{#1}

%% Set initial values
\FPadd\X{\X}{0.0000000001} % avoid overflows and divisions by zero
\FPset\Zi{\X}
\FPset\Di{1}
\FPset\Dprevious{0}
%% begin loop
\loop\ifnum\count@<13
%% numerator term
\FPtrunc\temp{\Zi}{0} 
\FPsub\temp{\Zi}{\temp}
%% inverse
\FPdiv\Znext{1}{\temp}
%% Find Dnext
\FPtrunc\IntZnext{\Znext}{0}
%% Di x Int{Zi+1}
\FPmul\temp{\Di}{\IntZnext}
\FPadd\temp{\Di}{\Dprevious}
\FPset\Dnext{\temp}
\FPround\Dnext{\Dnext}{0}

%%% Find Ni+1
\FPmul\temp{\X}{\Dnext}
\FPround\temp{\temp}{0}
\FPset\Nnext{\temp}

\FPdiv\ratio{\Nnext}{\Dnext}

\(Z_i=\Znext\to \Nnext/\Dnext =\ratio\)

\FPset{\Dprevious}{\Dnext}
\FPset{\Di}{\Dprevious}
\FPset{\Zi}{\Znext}

\advance\count@ by1
\repeat
%% end of loop

\gdef\NUM{\Nnext}
\gdef\DEN{\Dnext}

\makeatother
}

\def\Test#1{%
  \DecimalToFraction{#1}
  %The number $#1=\frac{\NUM}{\DEN}$
}

\Test{0.25}
\end{document}

该代码基于使用“C”编程的算法,是我正在研究的其他东西的概念证明。不保证,只是在疯狂的时刻完成的概念证明:) 我相信在 Lua 中可以更容易地完成。

答案2

替换\pgfmathparse{#1/3.141592654}以下代码以根据给定的输入产生所需的输出:

\pgfmathparse{int(#1*326)/1024}

请注意,326 = ceil(1024 / pi)。

在我看来,它\pgfmathfloatgetfrac并没有像预期的那样工作。即使使用浮点例程,我也无法生成分数 1/7。因此,虽然上述代码应该适用于大部分 2 的幂的倍数,但不要指望它能适用于 1/13 之类的任何值。

相关内容