我希望能够自动输出类似\frac{\pi}{2}
输入数字的内容.5*pi
。
我使用过number printing
tikz 的一些宏(与库紧密相关fpu
,至少在 cvs 版本中可用)。
我的想法是将数字除以pi
,然后使用number format/frac
,然后将 添加\pi
到结果中。但由于出现舍入误差,它无法按预期工作。以下是2*pi
、1.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 之类的任何值。