答案1
如果宏的输出完全可扩展,我会将其存储在另一个宏中,该宏也会写入文件.aux
。该存储宏的名称应该是通用的,以便计算宏可以测试它是否存在,如果存在,则只需重复使用它。如果输入会导致内部出现问题,您可以使用从输入计算出的 MD5 校验和作为宏名称的一部分,\csname ... \endcsname
但对于数字等来说,这不是必需的。
使用梅森计算作为示例:
\documentclass{article}
\usepackage[english]{babel}
\usepackage{numprint}
\usepackage{bigintcalc}
\begin{document}
\npthousandsep{ }
\makeatletter
\def\Mersenne#1{%
\begingroup
\par\noindent\parindent=0pt
$M_{#1}=$\par
% Calculate if not defined yet
\@ifundefined{Mersenne@#1}{%
\def\exponent##1{\bigintcalcPow{2}{##1}}%
\expandafter\xdef\csname Mersenne@#1\endcsname{%
\bigintcalcSub{\exponent{#1}}{1}%
}%
}{}%
% Write to aux file
\immediate\write\@auxout{\noexpand\expandafter\gdef\noexpand\csname Mersenne@#1\noexpand\endcsname{\csname Mersenne@#1\endcsname}}%
% Print
\expandafter\numprint\expandafter{\csname Mersenne@#1\endcsname}%
\endgroup
}
\makeatother
\Mersenne{1279}
\end{document}
然后文件.aux
包含以下行,只要.aux
没有被删除或者由于编译错误而没有正确写入,就可以避免将来的重新计算:
\expandafter \gdef \csname Mersenne@1279\endcsname {10407932194664399081925240327364085538615262247266704805319112350403608059673360298012239441732324184842421613954281007791383566248323464908139906605677320762924129509389220345773183349661583550472959420547689811211693677147548478866962501384438260291732348885311160828538416585028255604666224831890918801847068222203140521026698435488732958028878050869736186900714720710555703168729087}
如果宏的输出不是完全可扩展的,甚至是脆弱的(即\edef
会导致错误),那么它可能会存储在一个框寄存器中。但这有几个缺点:它不能.aux
轻易地存储在文件中,因此在一次编译运行中,同一宏的多次使用是有限的。此外,排版也是固定的,例如,长数字的换行不会因每次使用而有所不同。