如果在为环境编写代码时首先需要随机生成器tikzpicture
,就像我的情况一样,那么很自然地会在 的第 89 节中寻找配方Tantau's TikZ Manual
。从昨天开始,我就可以开始使用expl3 L3fp's
rand
和randint
函数 - 迟做总比不做好!,我有理由重写我的小工具箱,其中包含少量的document commands
和相关的,cs_ functions
以替换pgfmath
为l3fp
。经过一些调整后,该工具箱可以完成以前所做的所有事情,而且做得更好,如下面的 MWE 中所述。
我的问题如下:pgfmath
我的工具箱中的 -variant 可能有什么用处?在哪些情况下只pgfmath
需要 就够了?当前的问题是rand
和randint
与random (0, 1, or 2 arguments)
以及相关的设置方法。然而,问题的更广泛范围涉及和中常见的seed values
许多其他函数的使用。floating point expressions
l3fp
mathematical expression
pgfmath
\documentclass{article}
% RN. 9 April 2017
% BRIEF DESCRIPTION:
% 1. \myRandomNumberLThreeFP uses rand() and randint() provided by Expl3's
% L3fp package.
% 2. \myRandomNumberPGFMATH uses the random function provided by pgfmath.
% ADVANTAGES of expl3 fp over pgfmath are:
% - Familiar syntax: for example ...
% (1) Allows the use of the familiar \int/fp_set/gset:Nn ... syntax to save
% a value to a variable, in place of the awkward
% \pgfmathsetmacro{<variable>}{random()}, etc.
% (2) pgfmath does not allow grouping in \cs_ functions - how then do I control
% local vs. global scope issues for the other variables resident in the
% same function?,
% (3) ignores the check-declarations argument: \l_rn_randomInteger_int and
% \l_rn_randomInteger_fp are nowhere declared,
% (4) flags compile ERROR if \int_use:N or \fp_use:N is used when printing
% variables;
% - Accuracy:
% (1) integers range -(10e16-1) to +(10e16-1) = 9,999,999,999,999,999 as
% opposed to (2e31-1) = 2,147,483,647 for pgfmath.
% NOTE: why then the "Number too big" error which persists even with all
% references to pgfmath removed?,
% (2) reals have 16 decimal digits as opposed to 5 decimal digits for pgfmath.
%=======================
\usepackage[check-declarations]{expl3}
\usepackage{xparse}
\usepackage{pgfmath}
%-----------------------
\ExplSyntaxOn
\int_new:N \g_rn_randomInteger_int
%\NewDocumentCommand\myRandomNumberLThreeFP{O{1}O{9999999999999999}} % "Number too big" error ?
\NewDocumentCommand\myRandomNumberLThreeFP{O{1}O{2147483647}}
{
\rn_randomInt_LThreePFG:nn {#1}{#2}
randint:~\int_use:N \g_rn_randomInteger_int ,~
rand():~\fp_eval:n {rand()} \\
}
\cs_new:Npn \rn_randomInt_LThreePFG:nn #1#2
{
\group_begin:
\int_gset:Nn \g_rn_randomInteger_int {\fp_eval:n {randint(#1,#2)}}
\group_end:
}
\NewDocumentCommand\myRandomNumberPGFMATH{O{1}O{2147483647}}
{
%\group_begin:
\rn_randomInt_PGFMATH:nn {#1}{#2}
random:~\l_rn_randomInteger_int,~
\pgfmathsetmacro{\l_rn_randomFloatingPoint_fp}{random()}
random():~\l_rn_randomFloatingPoint_fp \\
%\group_end:
}
\cs_new:Npn \rn_randomInt_PGFMATH:nn #1#2
{
%\group_begin:
\pgfmathsetmacro{\l_rn_randomInteger_int}{random(#1,#2)}
%\group_end:
}
\ExplSyntaxOff
%-----------------------
\begin{document}
1.~Expl3~L3fp Package:\\
\myRandomNumberLThreeFP
\myRandomNumberLThreeFP
\myRandomNumberLThreeFP
2.~pgfmath:\\
\myRandomNumberPGFMATH
\myRandomNumberPGFMATH
\myRandomNumberPGFMATH
\end{document}
答案1
这两个系统的设计目标有一些不同,这些不同可能是优点也可能是缺点,这取决于您的要求。该pgfmath
引擎不可扩展,只需要经典的 TeX 基元。另一方面,它l3fp
通过扩展工作,需要 LaTeX3 要求的扩展基元集:e-TeX 和\pdfstrcmp
/或等效项(另见下文)。
主要考虑因素包括
pgfmath
使用 TeX dimen 寄存器进行计算。这限制了精度,意味着没有内部值可以超过 ±16383.99999。另一方面,在内部l3fp
使用整数计算(\numexpr
),但使用允许 16 位精度的算法(目标是符合 IEEE754)。当然,这里在速度方面存在权衡。(请注意,确实pgf
允许根据所需工作的性质切换到更准确的 FPU。)pgfmath
使用赋值工作,而l3fp
通过纯扩展工作。可扩展计算在 TeX“需要数字”但确实意味着某些操作无法进行的上下文中很有用。特别是,pgfmath
将允许将框设置操作放置在里面一个表达式,而l3fp
只有先前设置的框的测量才是允许的。- 在 中实现的函数范围
pgfmath
比 中的大l3fp
。例如,pgfmath
涵盖了数组和双曲三角函数,而这两项目前在 中都不可用l3fp
。(请参阅 中的“待办事项”列表interface3
。) - 中的随机数
l3fp
需要引擎支持,而它们在 中直接实现pgfmath
。目前,这意味着 XeTeX 中无法使用随机值(它缺少所需的原语),尽管这种情况在未来的某个阶段可能会改变。(可以在没有原语支持的情况下实现可扩展的随机值,但这会很慢,而且总体而言,努力和结果之间的平衡并不合理。)