在 TeX 中实现 Sum 函数

在 TeX 中实现 Sum 函数

我该如何在 TeX 中实现一个函数来添加任意数量的数字?阅读注释\def,似乎它最多只能接受九个参数。我该如何创建一个函数来将任意大的数字列表相加?

答案1

我将假设输入的形式为

\addintegers{1 + 2 + 3}

IE由一系列由+符号和(可能)空格分隔的整数组成。我还假设解决方案不需要可扩展,我们只有 TeX3 基元可用,并且我们不必担心“大”值(大于寄存器可以容纳的值\count)。

为了在这里找到总和,我们需要对输入设置一个循环,一次抓取一个数字。我们知道+每个数字之间都有,所以这样做的方法是使用以下形式的宏

\def\foo#1+{% Code

因为这样会抓取到下一个 之前的所有内容+。然后我们需要确保+在用户输入之后有一个 ,并且我们有一些“标记”,我们可以将其测试为“循环结束”。为了进行实际的数学运算,TeX 提供了\count寄存器:我​​将在组内使用划痕,并使用 将结果发送到组外\expandafter

\catcode`\@=11 %
\def\addintegers#1{%
  \begingroup
    \count0=0\relax
    \addintegers@aux#1+\relax+\relax
}
\def\addintegers@aux#1+{%
  \ifx\relax#1\relax
    \expandafter\addintegers@end
  \else
    \advance\count0 by #1\relax
    \expandafter\addintegers@aux
  \fi
}
\def\addintegers@end#1\relax{%
  \expandafter\endgroup
  \number\count0 %
}
\catcode`\@=12 %
\addintegers{1}
\addintegers{1 + 2 + 3}
\addintegers{1 + 22 + 333}
\bye

这当然是一个相当受限的解决方案(例如,除非有符号,否则不会涉及减法+),但问题需要更多细节才能更进一步。完整的错误检查需要更复杂的东西。

如果 e-TeX 基元可用,则几乎不费吹灰之力就可以实现相同的扩展

\def\inteval#1{\number\numexpr#1\relax}
\inteval{1}
\inteval{1 + 2 + 3}
\inteval{1 + 22 + 333}
\bye

在这种情况下,计算可以包括+、、、和,正如 e- TeX所支持的(因此名称不同)。(e-TeX 还允许表达式中使用空格。-*/()


如果您希望可扩展地工作并且只使用 Knuth 的 TeX,那么这是可行的,尽管有点乏味。Heiko Oberdiekbigintcalc可以可扩展地对任意整数进行计算,而无需使用 e-TeX,因此我们可以利用它(它相当大):

\input bigintcalc.sty %
\catcode`\@=11 %
\def\addintegers#1{%
  \addintegers@auxi#1+\relax+\stop{0}%
}
\def\addintegers@auxi#1+{%
  \ifx\relax#1%
    \expandafter\addintegers@end
  \else
    \expandafter\addintegers@auxii
  \fi
    {#1}%
}
\def\addintegers@auxii#1#2\stop#3{%
  \addintegers@auxi#2\stop{\bigintcalcAdd{#1}{#3}}%
}
\def\addintegers@end#1\stop#2{#2}
\catcode`\@=12 %
\addintegers{1}
\addintegers{1 + 2 + 3}
\addintegers{1 + 22 + 333}

\bye

细节在于将输入分成单独的数字,如果不可用则bigintcalc“手动”进行计算。\numexpr

相关内容