在自定义命令中执行基本算术

在自定义命令中执行基本算术

令人讨厌的一点sparklines是它的冗长和对外部算法的依赖。例如,要描绘 16%、53%、31% 的三条形图,必须这样写:

\begin{sparkline}{4}
  \sparkspike .166 .302
  \sparkspike .500 1
  \sparkspike .834 .585 
\end{sparkline}

我会比较喜欢:

\threesparkline{0.16}{0.53}{0.31}

所以我的主要问题是我可以在 LaTeX 中进行基本的算术运算吗,例如除法和乘法、在三个参数中求最大值等?

或者,有没有我错过的更好的使用迷你图的方法?

更新:

在建议使用该calc包之后,我仍坚持以下尝试,这会导致和中的\real错误\ratio

\newcommand{\threespike}[3]{
    \newcounter{max}\setcounter{max}{\maxof{\maxof{\real{#1}}{\real{#2}}}{\real{#3}}}
    \newcounter{a}\setcounter{a}{\ratio{\real{#1}}{max}}
    \newcounter{b}\setcounter{b}{\ratio{\real{#2}}{max}}
    \newcounter{c}\setcounter{c}{\ratio{\real{#3}}{max}}    
    \begin{sparkline}{4}
      \sparkspike .166 a
      \sparkspike .500 b
      \sparkspike .834 c 
    \end{sparkline}
}

更新2:

我最终必须\ratio像这样直接完成工作:

\newcommand{\ratiofivespark}[7]{
    \begin{sparkline}{6}
      \sparkspike .1 \ratio{#2}{#1}
      \sparkspike .3 \ratio{#3}{#1}
      \sparkspike .5 \ratio{#4}{#1}
      \sparkspike .7 \ratio{#5}{#1}
      \sparkspike .9 \ratio{#6}{#1} 
    \end{sparkline}
}

传递的第一个参数确定了条形图的完整高度。请参阅已接受的答案,了解更强大的 LaTeX-Fu!

答案1

当然,您可以在 LaTeX 中进行基本的算术运算。您有多种选择。您可以使用标准 TeX \advance\multiply\divide。您可以使用calc包以更自然的方式进行算术运算(尽管我发现我不使用它)。您还可以使用 e-TeX 扩展\numexpr ... \relax

编辑:好的。我想我已经找到解决办法了。

\documentclass{article}
\usepackage{sparklines}
\usepackage{fp}
\newcount\slnum
\makeatletter
\newcommand\dosparkline[2][4]{%
        \FPset\slmax{0}%
        \FPset\slpos{0}%
        \slnum0
        \slparse#2,\relax
        \FPadd\sladvance{1}{\the\slnum}%
        \FPdiv\sladvance{1}\sladvance
        \count@\slnum
        \loop\ifnum\count@>0
                \advance\count@-1
                \FPdiv\sltemp{\csname sl@\the\count@\endcsname}\slmax
                \expandafter\let\csname sl@\the\count@\endcsname\sltemp
        \repeat
        \begin{sparkline}{#1}
                \count@0
                \loop\ifnum\count@<\slnum
                        \FPadd\slpos\slpos\sladvance
                        % The {} are necessary
                        \sparkspike \slpos{} \csname sl@\the\count@\endcsname{}
                        \advance\count@1
                \repeat
        \end{sparkline}
}
\def\slparse#1,#2\relax{%
        \FPset\sltemp{#1}%
        \FPmax\slmax\slmax\sltemp
        \expandafter\let\csname sl@\the\slnum\endcsname\sltemp
        \advance\slnum1
        \ifx\relax#2\relax\else
                \slparse#2\relax
        \fi
}
\makeatother
\begin{document}
\dosparkline[10]{16,53,31,25,10,45}

\dosparkline{.16,.53,.31}
\begin{sparkline}{4}
  \sparkspike .166 .302
  \sparkspike .500 1
  \sparkspike .834 .585 
\end{sparkline}

\end{document}

第一个\dosparkline显示可选参数,即宽度(在所有东西中!)。第二个显示您要求的内容,您可以在没有输出的情况下进行比较。您会注意到我没有匹配您的间距。您可以通过更改\sladvance计算方式来解决这个问题。

答案2

对于使用实数的计算,请查看fp包。如果您正在使用 LuaTeX,那么转为 Lua 将是最好的方法。

相关内容