LaTeX 将数字扩展为序数后缀

LaTeX 将数字扩展为序数后缀

对于我正在开展的一个项目,我想自动“计算”数字的序数后缀。我需要计算各种数字的序数,然后将它们写入外部文件(项目本身是一个完全自动化的议程)。但是,计算不同数字的序数会导致错误。我采用以下方式解决此问题:

\documentclass{article}

\usepackage{xstring}

\newcommand\meetingNumbersconly{}
\newcommand\lastMeetingNumbersconly{}

%% Determine superscript of given raw number
\newcommand\getSuperscript[1]{%
    \ifnum\lasttwo>10\ifnum\lasttwo<14 th\fi\else
        \ifnum\lastone>3 th\else%
        \ifnum\lastone=0 th\else%
        \ifnum\lastone=3 rd\else%
        \ifnum\lastone=2 nd\else st%
        \fi\fi\fi\fi%
    \fi%
}

\newcommand\meetingNumberDefault[1]{
    \StrRight{#1}{2}[\lasttwo]%
    \StrRight{#1}{1}[\lastone]%
    \renewcommand\meetingNumbersconly{\getSuperscript{#1}}
}

\newcommand\meetingNumberLast[1]{
    \StrRight{#1}{2}[\lasttwo]%
    \StrRight{#1}{1}[\lastone]%    
    \renewcommand\lastMeetingNumbersconly{\getSuperscript{#1}}
}

\meetingNumberDefault{2}
\meetingNumberLast{1}

% \newwrite\general
% \openout\general=information.txt
% \write\general{\lastMeetingNumbersc}
% \closeout\general

\begin{document}
    2\textsuperscript{\meetingNumbersconly} \& 1\textsuperscript{\lastMeetingNumbersconly}
\end{document}

这里的问题是,预期结果应该是2nd & 1st。但是输出是2st & 1st。我想我明白为什么会发生这种情况:\@@meetingNumbersconly\@@lastMeetingNumbersconly保持相同的值,但这不是意图。

解决方案很简单,只需在命令中移动以下代码即可\@getSuperscript

\StrRight{#1}{2}[\@lasttwo]%
\StrRight{#1}{1}[\@lastone]%

但是,这是不可能的,因为在代码的后面,我尝试使用 将上标写入外部文件\write\general{<li>\@@lastMeetingNumbersc</li>}。尝试这样做时,会出现其他错误。

另一个解决方案是为 制作两个命令\@getSuperscript,每个序数一个。因为我想让代码尽可能干净,所以我宁愿不这样做。

我已经花了几个小时来研究扩展,但我还没有找到实现目标的方法:获得预期的输出2nd & 1st,同时还能将预期的结果写入文件。除了重复的代码之外,还有人有什么建议吗?

提前致谢。

答案1

你的命令的问题在于,执行完之后\meetingNumberDefault{1},你将拥有\lasttwo2拥有\lastone2将会\meetingNumbersconly拥有\getSuperscript{2}、拥有不是 st(使用\show\meetingNumbersconly来查看)。然后,您再次执行将和\meetingNumberLast{1}更改为 的操作。然后当您使用它时,将获得和的最后一个值的后缀,因此您会在两种情况下都得到(只需尝试更改序言中和的顺序)。\lasttwo\lastone1\meetingNumbersconly\lasttwo\lastonest\meetingNumberDefault{2}\meetingNumberLast{1}

发生这种情况是因为\renewcommand没有评估定义,它只是商店它。要强制\getSuperscript扩展为stnd或任何其他,您需要\edef而不是\renewcommande中的\edef代表扩展)。如果您更改它,\meetingNumbersconly\lastMeetingNumbersconly将是ndst

但是,我建议您只使用该nth包(带有super上标选项):

\documentclass{article}
\usepackage[super]{nth}
\begin{document}
  \nth{2} \& \nth{1}
\end{document}

或者,如果您需要预先设置数字,那么可能是这样的:

\documentclass{article}

\usepackage[super]{nth}

\newcommand\meetingNumberDefault[1]{%
  \getmeetingnumber\meetingNumbersconly{#1}}
\newcommand\meetingNumberLast[1]{%
  \getmeetingnumber\lastMeetingNumbersconly{#1}}

\newcommand\getmeetingnumber[2]{%
  \begingroup
    \let\nthscript\relax
    \xdef#1{\nth{#2}}%
  \endgroup}

\meetingNumberDefault{2}
\meetingNumberLast{1}

\begin{document}
    \meetingNumbersconly\ \& \lastMeetingNumbersconly
\end{document}

两个示例都产生:

在此处输入图片描述

答案2

以下是 的实现expl3。如果\addordinal在操作中使用 ,\write它将以十进制形式输出数字,并将后缀作为 的参数输出\ORDINAL,您可以根据需要定义后缀(请不要将其定义为上标)。

\documentclass{article}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\addordinal}{m}
 {% #1 should be something that TeX interprets as an integer
  \int_to_arabic:n { #1 }
  \exp_args:Ne \ORDINAL { \deman_compute_suffix:n { #1 } }
 }

\NewDocumentCommand{\ORDINAL}{m}{\textsuperscript{#1}}% how ugly is it?

\cs_new:Nn \deman_compute_suffix:n
 {
  \int_case:nnF { #1 }
   {% special cases
    {11}{th}
    {12}{th}
    {13}{th}
   }
   { \__deman_compute_suffix_normal:n { #1 } }
 }

\cs_new:Nn \__deman_compute_suffix_normal:n
 {
  \int_case:nnF { \int_mod:nn { #1 } { 10 } }
   {
    {1}{st}
    {2}{nd}
    {3}{rd}
   }
   {th}
 }

\ExplSyntaxOff

\begin{document}

\addordinal{1}
\addordinal{2}
\addordinal{3}
\addordinal{4}
\addordinal{10}
\addordinal{11}
\addordinal{12}
\addordinal{13}
\addordinal{19}
\addordinal{20}
\addordinal{21}
\addordinal{100}
\addordinal{101}

A ``random'' number \addordinal{\time}

Emulate a write: \edef\writtenout{\addordinal{121}}
\texttt{\meaning\writtenout}

\end{document}

其思路是首先检查特殊情况 11、12 和 13;在其他情况下,根据最后一位数字附加后缀,并通过模 10 运算计算。

在示例中,最后\edef模拟了操作中发生的情况\write

在此处输入图片描述

相关内容