小于 2 31 -1 的数字

小于 2 31 -1 的数字

在我正在编写的 documentclass 中,用户将输入一个整数,例如,\lessonnumber一个可能带有多个前导零的整数,例如 4。04在文档中的某些地方,我需要完整形式(04),而在其他地方,我只需要通用形式(4)。我该如何实现这一点?

答案1

我引入了\stripzero,它可以与括号内的参数一起使用,也可以与括号外的参数一起使用。该参数可以是可扩展的宏。

宏以递归方式工作。 的定义\stripzero首先扩展其参数,这是允许对诸如 之类的宏进行操作所必需的\lessonnumber。 参数扩展后,它会调用递归例程,将下一个标记与 进行比较0。 如果不是零,它会打印该标记并停止。 如果标记是0,它会忽略/丢弃它,然后再次调用自身以查看下一个标记。

避免宏将 视为\else其下一个参数的诀窍是将 视为\expandafter宏,以便吸收\else。如果我将 递归调用\stripzero(而不是\stripzerohelp),则\expandafter就没有必要了。但是,双宏递归也不是最有效的,因此我让递归例程直接调用自身,同时保留\expandafter

\documentclass{article}
\def\stripzero#1{\expandafter\stripzerohelp#1}
\def\stripzerohelp#1{\ifx 0#1\expandafter\stripzerohelp\else#1\fi}
\begin{document}
\stripzero{4}

\stripzero 04

\stripzero 004

\stripzero{004}

\def\lessonnumber{00056}
\stripzero\lessonnumber

\stripzero{\lessonnumber}
\end{document}

在此处输入图片描述

Marc 提出了一个有趣的问题:如何处理纯零参数。上面的 MWE 将它们全部删除。但是,这可能不是我们想要的。0如果参数是一串零,则可能需要打印出单个零。

因此,我提供了以下替代实现,用于检查第一个非零标记。如果是数字,则其行为与以前相同。但如果后续标记不是数字,则它会断定该数字是一串纯零,并输出单个0

\documentclass{article}
\def\stripzero#1{\expandafter\stripzerohelp#1}
\def\stripzerohelp#1{\ifx 0#1\expandafter\stripzerohelp\else\checkrange{#1}#1\fi}
\def\checkrange#1{\ifx1#1\else\ifx2#1\else\ifx3#1\else\ifx4#1\else\ifx5#1\else%
  \ifx6#1\else\ifx7#1\else\ifx8#1\else\ifx9#1\else0\fi\fi\fi\fi\fi\fi\fi\fi\fi}
\begin{document}
\stripzero{4}

\stripzero 04

\stripzero 004

\stripzero{004}

\def\lessonnumber{00056}
\stripzero\lessonnumber

\stripzero{\lessonnumber}

\def\lessonnumber{000}
\stripzero{\lessonnumber}xyz
\stripzero\lessonnumber xyz
$\stripzero\lessonnumber\vec{x}$
\end{document}

在此处输入图片描述

答案2

小于 2 31 -1 的数字

如果该数字符合 TeX 的数字范围,则可以用 vanilla TeX 的方法来对该数字进行规范化\number

\number\lessonnumber\relax

末尾\relax的 (或空的花括号对)可防止 TeX 在 之后寻找更多数字\lessonnumber。可扩展版本必须使用不同的技巧:

\makeatletter
\newcommand*{\normalizedlessonnumber}{%
  \expandafter\@firstofone\expandafter{\number\lessonnumber}%
}
\makeatother

然后,结束的花括号将作为 TeX 数字扫描仪的阻止器,并且花括号将作为 的参数括号消失\@firstofone

可扩展的 e-TeX 版本附加了对某些算术运算的支持:

\the\numexpr(\lessonnumber)\relax

无限整数

\bigintcalcNum可以通过包对无限整数进行可扩展的规范化bigintcalc

\bigintcalcNum{\lessonnumber}

添加前导零

如果数字符合 TeX 的整数范围,则以下宏\padnum会添加前导零(取自我的回答对此问题)。

\makeatletter
\newcommand{\padnum}[2]{%
  \ifnum#1>1 \ifnum#2<10 0\fi
  \ifnum#1>2 \ifnum#2<100 0\fi
  \ifnum#1>3 \ifnum#2<1000 0\fi
  \ifnum#1>4 \ifnum#2<10000 0\fi
  \ifnum#1>5 \ifnum#2<100000 0\fi
  \ifnum#1>6 \ifnum#2<1000000 0\fi
  \ifnum#1>7 \ifnum#2<10000000 0\fi
  \ifnum#1>8 \ifnum#2<100000000 0\fi
  \ifnum#1>9 \ifnum#2<1000000000 0\fi
  \fi\fi\fi\fi\fi\fi\fi\fi\fi
  \expandafter\@firstofone\expandafter{\number#2}%
}
\makeatother

\padnum也是可扩展的,这意味着,它可以安全地用作文件名、标签名的一部分……

用法。第一个参数指定位数,必要时应以前导零填充。第二个参数是要格式化的数字。然后\padnum{3}{\lessonnumber}使用\lessonnumberas04将扩展为004

答案3

我将使用\num来自siunitx 包。如手册中所述,的输出\num是高度可配置的。要删除所有零,您只需输入

\num[minimum-integer-digits=1]{\lessonnumber}

(如果\lessonnumber000等,则会打印0。)要打印数字的“完整形式”,只需使用\lessonnumber\num[\lessonnumber]。相反,如果您想用\lessonnumber前导零填充三位数,您可以输入

\num[minimum-integer-digits=3]{\lessonnumber}

更多示例请参见以下输出

在此处输入图片描述

来自以下代码:

\documentclass{article}
\usepackage{siunitx}
\begin{document}

  \num[minimum-integer-digits=1]{04} \num[minimum-integer-digits=3]{4}

  \num[minimum-integer-digits=1]{004} \num[minimum-integer-digits=4]{4}

  \num[minimum-integer-digits=1]{00004444} \num{00004}

\end{document}

答案4

只需利用 TeX 在请求时去掉前导零的事实<number>

\documentclass{article}

\usepackage{xparse}

\ExplSyntaxOn
\DeclareExpandableDocumentCommand{\printnumber}{sm}
 {
  \IfBooleanTF{#1}
    { \int_to_arabic:n { #2 } }
    { #2 }
 }
\ExplSyntaxOff

\newcommand{\lessonnumber}{04}

\begin{document}

Full number: \printnumber\lessonnumber

Strip zero: \printnumber*\lessonnumber

\end{document}

实际上,如果没有*,宏\printnumber什么也不做;但是我们可以*根据需要使用来有选择地去除零。

在此处输入图片描述

局限性:仅可能达到 2 31 –1 的数字。

相关内容