我经常遇到这样的问题:我必须进行一些简单的计算,主要是两个或三个量的乘积和总和。我曾经使用fp
软件包,但它看起来确实有些无人维护。现在我尝试了pgfmath
和所有来自 Ti 的东西一样钾Z 方向它非常完整,文档齐全,并且有一个很好的 API 和很棒的语法。我正在使用 Ti钾无论如何,Z 都用于图形,因此在所使用的包方面没有额外的开销。
唯一让我担心的是性能。我可以设计一些测试来更好地了解pgfmath
比较速度有多快,但我认为我最好先四处打听一下:
有没有文章比较在 TeX 中执行简单算术的不同解决方案
包括基准吗?
当人们想要对有符号的小数进行乘法运算时,最佳做法是什么?精度和数量级都不必太高,因为这些数字用于排版,所以对于几百毫米的尺寸,精确到十分之一毫米左右就可以了。
答案1
fp
除了数学解析器之外pgf
,我想我还会xfp
在这里评估/LaTeX3 FPU。使用简单的测试设置,例如
\documentclass{article}
\usepackage{fp}
\usepackage{xfp}
\usepackage{tikz}
\usepackage{l3benchmark}
\ExplSyntaxOn
\cs_new_eq:NN \benchmark \benchmark:n
\ExplSyntaxOff
\FPmessagesfalse
\newsavebox{\testbox}
\begin{document}
\benchmark{\sbox{\testbox}{\FPupn\result{2 2 root 180 40 / pi * sin *}}}
\benchmark{\sbox{\testbox}{\fpeval{sqrt(2) * sind(40)}}}
\benchmark{\sbox{\testbox}{\pgfmathparse{sqrt(2) * sin(40)}}}
\end{document}
在我的系统上我得到
0.00556 seconds (2.03e4 ops)
5.06e-4 seconds (1.83e3 ops)
2.23e-4 seconds (819 ops)
毫不奇怪,fp
它是最慢的,因为它适用于大量地方。另一方面,该pgf
单元是最快的,但并不比 LaTeX3 代码快多少。该pgf
代码不可扩展,内部使用 dimens,以准确性换取速度。后者是完全合理的,但当然可能或不可能根据用例接受。
(为了进行测试,我fp
主要使用了 UPN 部分,因为它看起来最公平:其他两个选项提供表达式的解析......)
为了完整性,如果您使用 LuaTeX,那么您可以使用 Lua 执行相同的操作,速度非常快:
\benchmark{\sbox{\testbox}{\directlua{tex.print(math.sqrt(2) * math.sin(40))}}}
5.1e-5 seconds (187 ops)
在我的测试设置上给出几秒钟的时间。
当然值得注意的是,速度确实取决于确切的操作:如果我进行简单的求和,pgf
则 LaTeX3 FPU 是可以比较的:
\documentclass{article}
\usepackage{fp}
\usepackage{xfp}
\usepackage{tikz}
\usepackage{l3benchmark}
\ExplSyntaxOn
\cs_new_eq:NN \benchmark \benchmark:n
\ExplSyntaxOff
\FPmessagesfalse
\newsavebox{\testbox}
\begin{document}
\benchmark{\sbox{\testbox}{\FPupn\result{1.234 5 * 9.10 6.78 / +}}}
\benchmark{\sbox{\testbox}{\fpeval{1.234 * 5 + 6.78 / 9.10}}}
\benchmark{\sbox{\testbox}{\pgfmathparse{1.234 * 5 + 6.78 / 9.10}}}
\end{document}
给出
0.00231 seconds (8.42e3 ops)
2.25e-4 seconds (837 ops)
2.63e-4 seconds (930 ops)
如果你想要简单的尺寸计算,没有什么能比原始的更好,最明显的\dimexpr
是。比如
\the\dimexpr 1.2cm + 3.445cm\relax
2.64e-6 seconds (9.85 ops)
由我的系统上的基准代码“计时” :真的,非常快。
答案2
tl;dr:pgfmath
比快 10 倍fp
所以我去做了一个小测试,我觉得这个测试对于我的预期目的来说足够现实:排版几十页甚至几百页,每页进行十几个浮点乘法。
我的测试文档有大约 80 页排版材料,a1 = 6
使用 XeLaTeX 排版大约需要 秒pgfmath
;如果内容是原来的三倍,则需要b1 = 13
秒。相比之下,使用 进行相同操作fp
,则需要a2 = 37
和b2 = 107
秒。显然,这里必须有一定的开销,我使用 和 的假设来估算,( a1 - c ) * 3 = b1 - c
因此( a2 - c ) * 3 = b2 - c
开销约为c = 2.5
秒。减去该开销后,所需时间为a1c = 3.5
、b1c = 10.5
、a2c = 34.5
、b2c = 104.5
。
虽然这些测量都是粗略地进行,并且需要大量的手势,fp
但它们似乎仍然表明,pgfmath
。
这里仍然存在各种各样的回旋余地;我还没有检查是否fp
可以优化计算(这可能会缩小差距),我也没有使用pgfmathparse
和朋友的短路版本(这可能会扩大差距),但另一方面,1 / 10
比率不太可能轻易被取消。
我还没有用/LaTeX3 FPU 做过测试xfp
,正如约瑟夫·赖特;我确实在 CTAN 上查过这些东西,它看起来确实对 LaTeX 的未来非常有希望。它确实是前沿技术,而这些都不在我的 TeX Live 2016 安装中,我现在不愿意更新它。但肯定是未来需要考虑的事情。
我的数据与约瑟夫赖特的数据不同,因此请随意批评我的方法。