答案1
问题
\sage
和宏\sagestr
同时执行多项操作,其中一些操作不“可扩展”(实际上,它\ST@sage
执行大部分工作)。这与 的问题完全相同\ref
,后者直接由 调用\ST@sage
。幸运的是,在这种情况下,有办法设计一个可扩展的接口;这就是 和 等包refcount
所做zref
的。这个想法很简单:
在仅扩展上下文中,你可以使用“可扩展”命令1来检索与引用关联的标记,我们将其称为福巴此处。此命令可能会根据测试结果扩展为各种标记序列,但无法打印错误消息或执行分配(LuaTeX 除外,这些操作无法在仅扩展的上下文中完成)。如果福巴您要求的引用已定义,命令扩展为与此引用关联的标记(就您而言,这将是 Sage 计算的结果)。
在你可以做更多事情的地方,而不仅仅是扩展标记,你使用第二个命令来告诉 LaTeX 你已经使用了引用福巴。然后,如果 LaTeX 发现该引用福巴未定义(因为例如在我们的例子中 Sage 尚未运行),它会记住并在运行结束时警告您某些引用未定义,您需要重新运行某些内容(此处为 Sage)。
在我们的例子中,在这两个命令之前还需要第三个命令:将您选择的宏(我们称之为\macro
)与 Sage 表达式关联起来,以便将表达式写入.sagetex.sage
文件以供 Sage 稍后处理。然后您可以使用诸如\estGet{\macro}
恢复以可扩展的方式Sage 计算的表达式的值。这里\estGet
是来自包的宏expsagetex
,我为这个答案编写了它,可以很容易地获得所需的结果。
解决方案expsagetex
expsagetex
有可用的 LaTeX 包吗这里。它是顶层,sagetex
允许以可扩展的方式从 Sage 检索结果。我将在下面解释如何使用它,但您可能希望从快速开始节选自论文目录(源代码这里)。这是一个包含教程、许多示例和解释的文件。
使用expsagetex
,您的问题可以按如下方式解决。两个示例文件都可以使用以下命令进行编译:
pdflatex document.tex
sage document.sagetex.sage
pdflatex document.tex
(或者,您也可以使用lualatex
或xelatex
)。
不带自动换行
\documentclass{article}
\usepackage{expsagetex}
\usepackage{siunitx}
\sisetup{group-separator = \,}
\setlength{\parindent}{0pt}
\begin{document}
With \verb|\estRecordFormatted|:\smallskip
\estRecordFormatted{\myIntRef}{2**233}%
\num{\estGet[-1]{\myIntRef}}%
\estRefUsed{\myIntRef}
\medskip
With \verb|\estRecordStr|:\smallskip
\estRecordFormatted{\myIntRefII}{str(2**233)}%
\num{\estGet[-1]{\myIntRefII}}%
\estRefUsed{\myIntRefII}
\end{document}
如果你想重用x
由以下方式定义的 Python 变量:
\begin{sageblock}
x = 2**333
\end{sageblock}
当然,您也可以通过替换来实现这一点,例如,将其替换\estRecordFormatted{\myIntRef}{2**233}
为\estRecordFormatted{\myIntRef}{x}
。这是因为在重要的上下文中,和2**333
都是x
计算同一对象的 Python 表达式:您要打印的整数。
具有自动换行功能
如果您希望数字自动换行,可以不使用siunitx
并从中获得的数字,然后对其进行后处理,expsagetex
以便在适当的位置插入水平粘连。以下是使用 实现此目的的方法expl3
:
\documentclass{article}
\usepackage{expsagetex}
\usepackage{xparse}
\ExplSyntaxOn
\regex_const:Nn \c_cis_regex { ( \cB\{ \c[LO]. \cE\} ){3} }
\tl_new:N \l_cis_tmpa_tl
\cs_generate_variant:Nn \tl_reverse_items:n { V }
\prg_generate_conditional_variant:Nnn \tl_if_eq:nn { Vx } { TF }
% #1: separator
% #2: “number”
\cs_new_protected:Npn \cis_seperate_thousands:nn #1#2
{
\tl_set:Nx \l_cis_tmpa_tl { \tl_reverse_items:n {#2} }
\tl_set:Nn \l_tmpa_tl {#1}
\regex_replace_all:NnN \c_cis_regex
{ \0 \cB\{ \u{\l_tmpa_tl} \cE\} } \l_cis_tmpa_tl
\tl_set:Nx \l_cis_tmpa_tl { \tl_reverse_items:V \l_cis_tmpa_tl }
\tl_if_eq:VxTF \c_space_tl { \tl_head:N \l_cis_tmpa_tl }
{ \tl_tail:N \l_cis_tmpa_tl }
{ \tl_use:N \l_cis_tmpa_tl }
}
\cs_generate_variant:Nn \cis_seperate_thousands:nn { nx }
% The default separator (\,) is unbreakable.
\NewDocumentCommand \separateThousands { O{\,} m }
{ \cis_seperate_thousands:nx {#1} {#2} }
\NewDocumentCommand \thinbreakablespace { }
{ \hspace{.16667em plus 0.01em} }
\ExplSyntaxOff
\setlength{\parindent}{0pt}
\begin{document}
With \verb|\estRecordFormatted|:\smallskip
\estRecordFormatted{\myIntRef}{2**233}%
\separateThousands[\thinbreakablespace]{\estGet[-1]{\myIntRef}}%
\estRefUsed{\myIntRef}
\medskip
With \verb|\estRecordStr|:\smallskip
\estRecordFormatted{\myIntRefII}{str(2**233)}%
\separateThousands[\thinbreakablespace]{\estGet[-1]{\myIntRefII}}%
\estRefUsed{\myIntRefII}
\end{document}
在这里,您也可以x
按照与上面解释的完全相同的方式使用变量作为输入。
使用expsagetex
以下是如何使用的说明expsagetex
,以补充当前可用的文档(论文目录,LaTeX 源)。
函数
\est*Record*
(\est[GA]RecordStr
、\est[GA]RecordFormatted
和\est[GA]RecordFloat
)都是本答案第一部分中描述的“第三种”命令。调用\estRecordStr{\macro}{sage expression}
记录文件sage expression
中的内容.sagetex.sage
并将结果输出与 关联\macro
。此后,\macro
将扩展为整数,但您不需要知道这一点。您需要它来恢复 Sage 计算的值,方法是将其传递给\estGet
。您还应该将其传递给\estRefUsed
(见下文)。这些
\est*Record*
函数在本地分配,除了名称中\macro
带有 的函数,它们是全局分配的。G
名称中
\est*Record*
带有A
before 的函数(A 代表“关联数组”)接受两个参数,而不是单个参数。例如,相当于其中是通过扩展一次获得的控制序列标记。Record
\macro
\estARecordStr{base}{\whatever-\you-\want}{sage expression}
\estRecordStr{\res}{sage expression}
\res
\csname base@\whatever-\you-\want\endcsname
\estRecordFormatted{\macro}{sage expression}
与 类似\estRecordStr{\macro}{sage expression}
,不同之处在于它存储latex(sage expression)
而不是仅仅存储sage expression
在文件中。如果 Sage 中的评估结果包含指数、括号等内容,.sagetex.sage
这可能会在从中获得的 LaTeX 代码中引入数学模式命令。sagetex
str(sage expression)
\estRecordFloat{\macro}{sage expression}{format}
用于以特定格式记录浮点数。例如,如果格式是.10f
,这将格式化浮点数,就像您"%.10f" % (sage expression,)
在 Python 中发出的那样,即:结果将格式化为 10 位小数,并且不会使用指数表示法。如果您需要更多的灵活性,请使用\estRecordStr
(如果您需要 Python 代码的百分号,则可以使用或的常量\percent
提供的宏)。sagetex
expl3
\c_percent_str
\estGet
是以可扩展方式检索结果的命令。更准确地说,\estGet[fallback]{\macro}
最终扩展为与 相关联的结果\macro
(\est*Record*
结果包装在 中\exp_not:n
,又名\unexpanded
)。第一个参数倒退是可选的,当 对应的引用\macro
尚未定义时使用(可能意味着您需要在 .sagetex.sage 文件上运行 Sage)。当您在默认的 ,即,会导致错误的\estGet
地方调用时(例如,在的命令的强制参数中),此参数特别有用。??
siunitx
\num
\estRefUsed{\macro}
是您应该做的,以表明您的代码使用与 相关联的结果\macro
。如果引用尚未定义,这将生成相应的警告,否则它根本不会执行任何操作。您应该\estGet[fallback]{\macro}
在文档中的某个地方使用它。由于\estRefUsed
不可扩展,您通常会在附近调用\estGet
和,但不会完全在同一个位置。例如:\estRefUsed
\estRecordFormatted{\mymacro}{2**5} % record the expression 2**5 \edef\myresult{\estGet[0]{\mymacro}} % store result in \myresult \estRefUsed{\mymacro} % warn if it's not in the .sout file yet \show\myresult % show result on terminal
在此示例中,在 内使用
\estRecordFormatted
或是不正确的。\estRefUsed
\edef
在这些宏中,只有\estGet
是可扩展的(以及它的expl3
姊妹\est_get:nnn
)。但这是最重要的一个,您可以在\edef
、\write
、\fpeval
、\num
和许多其他地方使用它。例如,如果它从 Sage 检索到的内容是合适的类型,您可以\estGet
在计算中间\fpeval
、计数器或长度(dimen 或 skip)寄存器分配等中使用。您甚至可以使用它来计算许多点的坐标,以便用 Ti 绘制图钾Z,pgfplots
或任何其他基于 TeX 的绘图框架。所有这些内容的示例都在论文目录; 看看它的LaTeX 源。 可能性是无止境!
脚注
- 在这个答案中,我们说一个命令是“可扩展的”,如果它在 中使用时能正确地完成它的工作
\edef
,即:它可以扩展到它被设计为的任何扩展,而不会产生任何不必要的副作用。这个属性通常被称为“完全可扩展”,但这个术语并不是真正固定的。至少 Heiko Oberdiek 使用的术语“可扩展”与我在他的一些软件包手册中使用的相同(如果我没记错的话),因此我觉得这样做相对安全。:-)
答案2
这有点笨重,但对我来说很有用:
\documentclass{report}
\usepackage{sagetex}
\usepackage{siunitx}
\sisetup{group-separator = \text{\,}}
\begin{document}
\begin{sageblock}
x=2^333
\end{sageblock}
\begin{sagesilent}
start="\\num{"
end="}"
\end{sagesilent}
Works: \sage{x}
Works, too: \sagestr{start+latex(x)+end}
\end{document}