计数器
原 文:Counters
译 者:Xovee
翻译时间:2022年3月16日
LaTeX 计数器介绍
基于 LaTeX 的排版可以看作是一种特殊的编程:你使用排版语言(LaTeX 命令)来控制最终的效果:也就是我们最终生成的 PDF 文件。如同所有的其他编程语言一样,你需要使用 LaTeX 来存储变量,随后使用它们,例如
- 在文档中输入那些存储的变量
- 提供自动编号
- 使用它们来实现条件代码或者循环
- 改变它们的值(例如增减)
- 将它们的值重置为完全不一样的数字
这种基于变量的处理过程广泛地存在于“正规”的编程语言之中,例如 Javascript 和 Lua 等:你声明一个变量,然后给它进行赋值。LaTeX 也提供了类似的功能,不过其表现形式有很大不同。我们将在本文的之后部分进行详细的阐述。
从本质上来说,一个 LaTeX 计数器即是“LaTeX 变量”,用来存储整数值。LaTeX 本身也用到了数字计数器来对页面、章节、图表、列表等元素进行编号。本文将会介绍如何获取和编辑这些计数器,以及如何去创建这些计数器。
计数器相关的命令
下面列出了常用的 LaTeX 计数器命令。
创建和递增:
\newcounter{somecounter}[anothercounter}
\setcounter{somecounter}{number}
\addtocounter{somecounter}{number}
\stepcounter{somecounter}
\refstepcounter{somecounter}
访问和输出:
\arabic{somecounter}
\roman{somecounter}
\Roman{somecounter}
\alph{somecounter}
\Alph{somecounter}
\fnsymbol{somecounter}
\value{somecounter}
其他:
\counterwithin{somecounter}{anothercounter}
\counterwithout{somecounter}{anothercounter}
创建计数器、增加数值
\newcounter{somecounter}[anothercounter}
用来创建一个新的计数器。第二个在方括号之中的参数是可选的,它的作用是:当anothercounter
计数器改动的时候,定义somecounter
为一个新的计数器。\newcoutner
命令由于其简单性而被频繁的使用,它创建somecounter
计数器并将其初始化为 0。
- 注意:每个被
\newcounter
命令创建的计数器同时定义了一个新的命令,用来录入计数器的值。例如,\newcounter{mycounter}
定义了一个叫做\themycounter
的命令。下面的代码展示了这个例子:
\newcounter{mycounter}
\setcounter{mycounter}{42}
You can now write \verb|\themycounter| to obtain \themycounter.
这段代码的输出为:
You can now write \themycounter to obtain 42.
- 注意:如果
mycounter
已经被定义了,那么 LaTeX 会抛出一个错误c@mycounter already defined
。
\setcounter{somecounter}{number}
让somecounter
计数器的值为value
。
- 注意:
value
可以为正数也可以为负数。
下面展示一个例子:
\noindent Create a new counter \texttt{myvar} and assign it the value \texttt{42}.
\vspace{10pt}
\newcounter{myvar}
\setcounter{myvar}{42}
\noindent Writing \verb|\themymar| typesets \texttt{\themyvar}.
\vspace{10pt}
\noindent Next, we'll change \texttt{myvar} to \texttt{-42}, writing \verb|\setcounter{myvar}{-42}|
\setcounter{myvar}{-42}. Now, writing \verb|\themyvar| outputs \texttt{\themyvar}.
\addtocounter{somecounter}{number}
将somecounter
计数器的值增大number
。
- 注意:
number
可以为正数也可以为负数。如果是负数的话就是减少当前计数器的值。
\addtocounter{somecounter}{-1} % decreases somecounter by 1
\noindent Create a new counter \texttt{myvar} and assign it the value \texttt{42}.
\vspace{10pt}
\newcounter{myvar}
\setcounter{myvar}{42}
\noindent Writing \verb|\themymar| typesets \texttt{\themyvar}.
\vspace{10pt}
\noindent Next, we’ll change \texttt{myvar} to \texttt{142} by writing \verb|\addtocounter{myvar}{100}|\addtocounter{myvar}{100}. Now, writing \verb|\themyvar| outputs \texttt{\themyvar}.
\stepcounter{somecounter}
将somecounter
计数器的值加一。例子:
If we create a new counter by writing \verb|\newcounter{mycounter}|
\newcounter{mycounter} then the counter \texttt{mycounter} is created and
initialized to zero, as you can see if you write \verb|\themycounter|:
\texttt{mycounter} currently stores: \themycounter.
If we now write \verb|\stepcounter{mycounter}|\stepcounter{mycounter} then
\verb|\themycounter| now contains the value \themycounter.
\refstepcounter{somecounter}
将somecounter
计数器的值加一,并使其对交叉引用机制可见。
下面的例子使用\refstepcounter
来对example
环境创建一个新的计数器,并且使用\label
和\ref
来提供交叉引用功能。
\documentclass{article}
\newcounter{example}[section]
\newenvironment{example}[1][]{\refstepcounter{example}\par\medskip
\noindent\textbf{Example~\theexample. #1} \rmfamily}{\medskip}
\begin{document}
\section{Three examples}
\begin{example}
Create a label in this first example \verb|\label{ex:1}|\label{ex:1}. This is the first example. The \texttt{example} counter will be reset at the start of each new each document \verb|\section|.
\end{example}
\begin{example}
And here's another numbered example. Create a second \verb|\label{ex:2}|\label{ex:2} to later reference this one. In Example \ref{ex:1} we read... something.
\end{example}
\begin{example}
And here's another numbered example: use \verb|\theexample| to typeset the number currently assigned to the \texttt{example} counter: it is \theexample.
\end{example}
\section{Another section}
We've just started a new section meaning that the \texttt{example} counter has been set to \theexample.
We'll reference examples from the previous section (Examples \ref{ex:1} and \ref{ex:2}). This is a dummy section with no purpose whatsoever but to contain text. The \texttt{section} counter for this section can be typeset using \verb|\thesection|: it is currently assigned the value of \thesection.
\begin{example}
This is the first example in this section: the \texttt{example} counter has been stepped and now set to \theexample.
\end{example}
\end{document}
总结
在这个例子中,我们定义了新的环境example
,这个环境有三个与计数器有关的命令:
\newcounter{example}[section]
:创建一个新的名为example
的计数器,当section
计数器增加的时候,example
计数器将会被重置为 0。你可以在方括号中制定其他计数器,也可以不适用这个参数,如果你不想让这个计数器自动重置的话。\refstepcounter{example}
:将example
计数器加一,并且让其对交叉引用机制可见。此时你可以使用\label
命令。theexample
:打印计数器example
的值。
更多有关用户自定义环境的信息请参考这篇文章。
获取以及打印计数器的值
下面的内容基于 LaTeX 默认的设置。
\arabic{somecounter}
1, 2, 3…
\roman{somecounter}
、\Roman{somecounter}
i, ii, iii, iv…
I, II, III, IV…
- 注意:如果为负数则不打印任何值。如果数字过大的话,计算会花费很久的时间,并且输出会很长。
- 小技巧:如果你对 TeX 如何转换阿拉伯数字到罗马数字感兴趣的话,可以看这篇文章。
\alph{somecounter}
、\Alph{somecounter}
小写字母、大写字母
a=1, b=2, c=3…
A=1, B=2, C=3…
- 注意:值必须小于等于 26,大于等于 1,否则会报错。
\fnsymbol{somecounter}
计数器值 | 输出 |
---|---|
1 | * |
2 | † |
3 | ‡ |
4 | § |
5 | ¶ |
6 | ∥ |
7 | ∗∗ |
8 | †† |
9 | ‡‡ |
打印计数器值的一些例子
下面的例子介绍如何使用计数器来打印值。
\newcounter{somecounter}
\setcounter{somecounter}{9}
\begin{itemize}
\item \verb|\arabic{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \arabic{somecounter}
\item \verb|\roman{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \roman{somecounter}
\item \verb|\Roman{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \Roman{somecounter}
\item \verb|\alph{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \alph{somecounter}
\item \verb|\Alph{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \Alph{somecounter}
\item \verb|\fnsymbol{somecounter}| typesets the \texttt{somecounter} value of \thesomecounter{} as \fnsymbol{somecounter}
\end{itemize}
输出:
\value{somecounter}
当 LaTeX 期望去处理一个数值的时候,你可以使用这个命令。
(可选)这个命令的一些背景知识
似乎\value{counter}
是一个用来输出计数器值的命令,但不是这样的。设计它的目的是将其与其他 LaTeX 命令搭配使用:读取这个计数器的值,并将其看做是一个 TeX 数字。而命令\thesomecounter
的作用是打印counter
的值。
在 LaTeX 内部,\value
的定义为:
\def\value#1{\csname c@#1\endcsname}
\value{somecounter}
会创建一个 LaTeX 内部控制序列 \c@somecounter
的实例,这个实例包含somecounter
的值。
例子
下面的例子介绍了\value
的基本用法:
\noindent Start by declaring two new counters:
\begin{verbatim}
\newcounter{first}
\newcounter{second}
\end{verbatim}
\newcounter{first}
\newcounter{second}
\noindent Sometime later in your code you set their values:
\begin{verbatim}
\setcounter{first}{100}
\setcounter{second}{50}
\end{verbatim}
\setcounter{first}{100}
\setcounter{second}{50}
\noindent Then you write more \LaTeX{} code...\vspace{10pt}
\noindent At some point we might want to add the value of counter \texttt{second} to counter \texttt{first}. One way to do that is using \verb|\value| to obtain the \textit{current} value stored in the \texttt{second} counter:
\begin{verbatim}
\addtocounter{first}{\value{second}}
\end{verbatim}
\addtocounter{first}{\value{second}}\noindent The value of \texttt{first} can be output by \verb|\thefirst|: \thefirst. We can also write \verb|\the\value{first}| which also typesets \the\value{first}. However, writing \verb|\value{first}| will generate the error \texttt{Missing number, treated as zero} because \LaTeX{} then tries to execute the internal command \verb|\c@first|. Uncomment the following line to generate the error:
\begin{verbatim}
%\value{first}
\end{verbatim}
%\value{first}
这段代码的输出是:
其他计数器命令
现在我们介绍\counterwithin
和\counterwithout
命令。chngcntr
包的文档中说明了这两个命令的作用:
\counterwithin
:
有些时候我们希望由
\newcounter{<ctr>}
定义的计数器可以变成由\newcounter{<ctr>}[<within>}
定义的计数器。这个时候,我们可以使用\counterwithin{<ctr>}{<within>}
命令来达到这一点。
\counterwithout
:
恰恰相反,这个命令将由
\counterwithin{<ctr>}{<within>}
创建的计数器变为由\newcounter{<ctr>}
命令创建的计数器。
本质上来说,这两个命令的作用是将两个已经定义好的计数器联结起来,或者使它们分离。
\counterwithin{somecounter}{anothercounter}
在anothercounter
变化的时候,重置somecounter
的值为0,这个机制将两个计数器连接了起来。除了创建了一个连接,这个命令重新定义了\thesomecounter
的输出:<value of anothercounter>.<value of somecoutner>
,而不是somecounter
。加星号的命令\counterwithin*{somecounter}{anothercounter}
则不会改变somecounter
的输出。
\documentclass{article}
\begin{document}
\section{A short example}
\newcounter{example}
\counterwithin{example}{section}
\newcounter{exampletwo}
\counterwithin*{exampletwo}{section}
\setcounter{example}{100}
\setcounter{exampletwo}{100}
\begin{itemize}
\item \verb|\theexample| typesets \theexample
\item \verb|\theexampletwo| typesets \theexampletwo
\end{itemize}
\end{document}
上面的代码的输出为:
你可以在\counterwithin
中使用一些 LaTeX 提供的标准计数器,例如:
section
:使用\section
命令equation
:使用equation
环境
或者其他你所创建的计数器。
\counterwithin
和coutnerwithin*
的例子
下面的代码提供了更多使用这两个命令的例子:
\documentclass{article}
\counterwithin{equation}{section}
\newcounter{example}
\counterwithin*{example}{section}
\newenvironment{example}[1][]{%
\stepcounter{example}%
\par\vspace{5pt}\noindent
\fbox{\textbf{Example~\thesection.\theexample}}%
\hrulefill\par\vspace{10pt}\noindent\rmfamily}%
{\par\noindent\hrulefill\vrule width10pt height2pt depth2pt\par}
\begin{document}
\section{First equation}
Some introductory text...
\begin{example}
\begin{equation}
f(x)=\frac{x}{1+x^2}
\end{equation}
\end{example}
\subsection{More detail}
\begin{example}
Here we discuss
\begin{equation}
f(x)=\frac{x+1}{x-1}
\end{equation}
... but don't say anything
\end{example}
\subsubsection{Even more detail}
\begin{example}
\begin{equation}
f(x)=\frac{x^2}{1+x^3}
\end{equation}
\begin{equation}
f(x+\delta x)=\frac{(x+\delta x)^2}{1+(x+\delta x)^3}
\end{equation}
\end{example}
\section{Third equation}
\begin{example}
The following function...
\begin{equation}
f_1(x)=\frac{x+1}{x-1}
\end{equation}
..is a function
\begin{equation}
f_2(x)=\frac{x^2}{1+x^3}
\end{equation}
\begin{equation}
f_3(x)=\frac{3+ x^2}{1-x^3}
\end{equation}
\end{example}
\end{document}
代码总结:
\newcounter{example}
:对环境example
创建一个新的计数器\counterwithin*{example}{section}
:将example
计数器和section
计数器连接起来:每一次我们使用\section
命令的时候,example
计数器将会置零。如果不想重定义\theexample
的输出,我们可以使用带星号的版本。- 然后,我们创建了一个新的环境
example
。对于这个环境我们使用\stepcoutner{example}
来对这个环境进行计数。我们使用\textbf{Example~\thesection.\theexample}
来输出Example<section number>.<example number>
。
\newenvironment{example}[1][]{%
\stepcounter{example}%
\par\vspace{5pt}\noindent
\fbox{\textbf{Example~\thesection.\theexample}}%
\hrulefill\par\vspace{10pt}\noindent\rmfamily}%
{\par\noindent\hrulefill\vrule width10pt height2pt depth2pt}
\counterwithout{somecounter}{anothercounter}
这个命令移除了这两个计数器的连接。对于任意两个计数器,你可以使用\counterwithout
和\counterwithin
来改变它们的连接状态。如下面的例子所示:
\section{First equation}
\begin{example}
\begin{equation}
f(x)=\frac{x}{1+x^2}
\end{equation}
\end{example}
\subsection{Second equation}
\begin{example}
\begin{equation}
f(x)=\frac{x+1}{x-1}
\end{equation}
\end{example}
\vspace{6pt}\noindent Note how the \texttt{example} counter is reset at the start Section \ref{sec:n0}.
\section{Third equation}
\label{sec:n0}
\begin{example}
\begin{equation}
f(x)=\frac{x+1}{x-1}
\end{equation}
\end{example}
\vspace{6pt}\noindent Here, we wrote \verb|\counterwithout{example}{section}| so that \texttt{example} is no longer reset at the start of a section. In Sections \ref{sec:n1} and \ref{sec:n2} the \texttt{example} counter keeps increasing. \counterwithout{example}{section}
\section{Fourth equation}
\label{sec:n1}
\begin{example}
\begin{equation}
f(x)=\frac{x^2+x^3}{1+x^3}
\end{equation}
\end{example}
\section{Fifth equation}
\label{sec:n2}
\begin{example}
\begin{equation}
f(x,k)=\frac{x^2-x^k}{1+x^3}
\end{equation}
\end{example}
例子
enumerate
这个环境使用四种层级的计数器:
层级 | 计数器变量 |
---|---|
1 | enumi |
2 | enumii |
3 | enumiii |
4 | enumiv |
这些计数器可以由\setcounter
命令改变。请看下面的例子(虽然不是最佳的方案,具体可以参考这篇文章):
This example shows one way to change the numbering of a list; here, changing the value of the \texttt{enumi} counter to start the list numbering at 4 (it is incremented by the \verb|\item| command):
\begin{enumerate}
\setcounter{enumi}{3}
\item Something.
\item Something else.
\item Another element.
\item The last item in the list.
\end{enumerate}
输出:
LaTeX 中的默认计数器
用途 | 名称 |
---|---|
文档结构 | part, chapter, section, subsection, subsubsection, paragraph, subparagraph, page |
浮动元素 | equation, figure, table |
脚注 | footnote, mpfootnote |
enumerate 环境 | enumi, enumii, enumiii, enumiv |