整理一下 LaTeX 关于数学公式、数学字体以及相关的细节内容。

AMS宏包

AMS 提供了一系列最常用的 LaTeX 数学宏包:

  1. amsmath 宏包:
    • 提供了一套增强的数学排版命令和环境,使得数学公式的编辑和排版更加灵活和方便。
    • 引入了一些新的数学环境,例如 aligngather,以便更好地控制多行公式的排版。
    • 提供了诸如 \text, \DeclareMathOperator 等命令,用于在数学模式中插入文本或定义新的运算符。
  2. amssymb 宏包:扩展了 amsmath,提供了额外的数学符号,如各种箭头、关系符号、集合符号等。
  3. amsfonts 宏包:提供了一些额外的字体,例如 \mathbb 命令用于黑板粗体字母。
  4. amsthm 宏包:提供了 theorem, lemma, proof 等定理或证明环境,方便用户在文档中定义和使用定理。

下面的数学公式绝大部分都需要这些宏包,默认已经被导入

1
\usepackage{amsmath,amssymb,amsfonts,amsthm}

这些宏包在实际使用时似乎要注意一下导入的先后顺序,例如最好先调用 amsmath 再调用 amsthm,参考 LaTeX 宏包介绍(一)—— amsthm 阅读笔记

数学公式

行内公式直接使用 $...$ 包裹即可,也可以使用 \(...\) 包裹,关于哪一种更好并没有统一的结论,chktex建议使用后者,但是大部分教程都建议使用前者。

本文主要关注的是行间公式,TeX 默认的行间公式环境为 $$...$$,这也是 markdown 支持的行间公式,但是在 LaTeX 中并不推荐使用它,虽然在大多数情况下是没有问题的,但是在某些情况下和推荐使用的 \[\] 以及其它行间公式环境的表现并不一样。

这里重点关注了编号和多行公式这两个问题,略去了其它内容,比如很多数学符号的处理。对于公式编号的基本原则是:只对必要的公式进行编号,而不是对所有行间公式进行编号。

对于行内公式,尽量不要包括标点符号,把标点符号放在行内公式的外面;对于行间公式,则需要考虑标点符号,根据上下文确定。

基本使用

基本的行间公式环境为 equation,例如

1
2
3
\begin{equation}
a^2 + b^2 = c^2
\end{equation}

公式自动带有编号并在右侧呈现,编号可能形如:1, 2, 3, 也可能是形如 1.1, 1.2 等基于章节的编号,默认行为取决于当前文档是 atricle 这类小型文本或 book 这类大型文本,当然也可以使用命令手动更改,例如

1
2
\numberwithin{equation}{section}
\numberwithin{equation}{subsection}

可以使用 \label{} 结合 \ref{}\eqref{} 来形成交叉引用(后者是宏包提供的,区别在于引用时自动给公式编号加了括号)

1
2
3
4
5
\begin{equation}
a^2 + b^2 = c^2 \label{eq:1}
\end{equation}

Equation \eqref{eq:1} is called `Gougu theorem' in Chinese.

效果如下

还可以使用 hyperref 宏包提供的 \autoref{} 命令来替代普通的 \ref{},它会自动在前面加上引用对应的计数器名称,例如 Figure XSection X 等,并且将整体作为链接。但是不建议使用它引用公式,因为它呈现的是 Equation X,看着很奇怪。

可以在行尾使用 \tag{xxx} 来手动修改编号,例如一个具有特殊意义的文本标记,此时行尾的编号和交叉引用都会替换为自定义的标记

1
2
3
4
5
\begin{equation}
a^2 + b^2 = c^2 \tag{aaa}\label{eq:2}
\end{equation}

Equation \eqref{eq:2} is called `Gougu theorem' in Chinese.

效果如下

注意 \tag{xxx} 的内部属于文本模式,如果需要在标记中使用数学公式,还需要 $$ 包裹。还有一个与 \tag 非常类似的 \tag* 命令,区别在于后者生成的标记不会被括号包裹。

可以在行尾使用 \notag 来抑制当前行的公式生成编号。(这个命令更常见的情景是在多行带编号的公式中选择性关闭某些行的编号)

1
2
3
\begin{equation}
1 + 1 \neq 3 \notag
\end{equation}

使用 \nonumber 也可以达到一样的效果。

有时需要使用完全不带编号的公式,可以使用 equation* 环境,更常见的选择是 \[\],它也提供了不带编号的行间公式环境,它实际上是 displaymath 环境的等价形式。

1
2
3
4
5
6
7
8
9
10
11
\begin{equation*}
a^2 + b^2 = c^2
\end{equation*}
For short:
\[
a^2 + b^2 = c^2
\]
Or if you like the long one:
\begin{displaymath}
a^2 + b^2 = c^2
\end{displaymath}

多行公式

一个常见的使用情景为罗列一组公式,按照中间的等号对齐,常用的环境为 align,它基于 & 对多行公式进行定位,通常将 & 放在等号左侧,在多行公式中使用 \\ 换行

1
2
3
4
\begin{align}
a & = b + c \\
& = d + e
\end{align}

默认情形下 align 环境的每一行都会产生一个编号,可以使用 \notag 去掉某行的编号,例如出现长公式换行时不需要两个编号。

有时也可能将 & 放在等号右侧,因为右侧有长公式需要换行,不能让加号和等号对齐,例如

1
2
3
4
5
6
\begin{align}
a ={} & b + c \\
={} & d + e + f + g + h + i + j + k + l \notag \\
& + m + n + o \\
={} & p + q + r + s
\end{align}

这里的使用 ={} & 是为了在对齐时产生更合适的间距。

对于多组公式的对齐,例如两行三列的公式可以如下表示,其中公式之间和等号旁都要加上 &

1
2
3
4
\begin{align}
a &=1 & b &=2 & c &=3 \\
d &=-1 & e &=-2 & f &=-5
\end{align}

除了默认的多行公式环境 align,还有几个常见的需求以及对应的变体,例如完全不使用编号的环境 align*,还有一个情景是多行公式被打包为一个整体进行编号,此时需要使用 aligned 环境,例如

1
2
3
4
5
6
7
8
\begin{equation}
\begin{aligned}
a &= b + c \\
d &= e + f + g \\
h + i &= j + k \\
l + m &= n
\end{aligned}
\end{equation}

alignalign*aligned 环境总是需要考虑对齐的标记放置,在使用比较麻烦,而且某些情况下的排版不够美观。 还有一组使用更简单的多行公式环境:gathergather*gathered 环境,它们的行为比较简单,将多行自动居中对齐, 在某些情况下的排版比 align 更加美观。

1
2
3
4
\begin{gather}
a + b + c = b + a \\
1 + 2 = 2 + 1
\end{gather}

复杂公式

如果需要分段函数之类的情况,cases 环境是很好的选择,例如

1
2
3
4
5
6
\begin{equation}
D(x)=\begin{cases}
1, & \text{if} x \in \mathbb{Q};\\
0, & \text{if} x \in \mathbb{R}\setminus\mathbb{Q}
\end{cases}
\end{equation}

对于长等式的一个常见需求是把其中一部分记作一个新记号,即在一部分项的下方使用长括号和新记号:

1
2
3
\[
\underbrace{1+1+1+1+1}_{(A)} + \underbrace{2+2+2+2+2}_{(B)} = 0
\]

这里的标记 (A) 可能偏小,可以手动调大一点。

有时存在一些简单的竖向公式排版的需求,下面提供一个例子作为参考

实现方式如下(基于 array 实现多行对齐,基于 \rotatebox 实现符号的旋转)

1
2
3
4
5
6
7
8
9
\[
k_0 \coloneqq \Vert \bm{k}_0 \Vert
= \begin{array}[t]{@{}c@{}}
\Vert \bm{k} \Vert \\
\rotatebox[origin=c]{90}{$=$} \\
k
\end{array}
=\frac{2\pi}{\lambda}
\]

参考 vertical and horizontal equations,更复杂的情况建议使用 tikz。

括号与定界符

Latex 提供了多种定界符(主要是括号)表示公式块的边界,包括最基本的三种括号:

  • 小括号 ()
  • 中括号 []
  • 大括号 \{\}(需要转义)(等价于 \lbrace\rbrace)。

尽量避免在公式中把中括号 [] 和大括号 {} 作为普通括号使用,主要使用小括号即可,尤其慎用中括号,因为有很多其它含义,容易引起歧义。

此外,还有常用于表示内积的尖括号 \langle\rangle(不是 <>),表示模和范数的单竖线 |(等价于 \vert)以及双竖线 \|(等价于 \Vert)。 这两种竖线命令本身是没有左右(开符号,闭符号)区分的,在实践中更建议用成对版本:(虽然在显示中没什么区别)

1
2
3
\[
\lvert b \rvert, \lVert b \rVert,
\]

常见的定界符如下图

如果定界符的高度不能盖住内部的公式块,看起来非常不舒服,可以使用 \left\right 命令可以在排版时自动调整括号(定界符)的大小,例如

1
2
3
\[
\left(\frac{1}{2x}\right)
\]

需要注意的是:

  • \left\right 必须成对使用,但是我们确实需要单独一个定界符的情况,此时不需要的部分用 \left.\right. 代替。
  • \left\right 包裹的公式块是不允许出现 \\ 断行的。(但是 aligned 等环境虽然内部有换行,但是在外部不被视作断行)
  • 为了和 \left\right 命令搭配,对内部的竖线需要使用 \middle| 命令,否则竖线的尺寸无法进行自适应调整。

有时我们对自动生成的定界符大小不满意,或者公式块必须要换行,可以使用 \big\bigg\Big\bigg 等命令进行手动调节,这些命令只作用于一个定界符,不需要成对。

箭头

LaTeX 提供了大量的箭头相关的命令,amsmath 又为其提供了更多支持,如下表。

其中几个常用的箭头有缩写指令:

  • \to 等价于 \rightarrow,向右的小箭头
  • \gets 等价于 \leftarrow,向左的小箭头
  • \iff 等价于 \Longleftrightarrow,向左向右的长箭头
  • \implies 等价于 \Longrightarrow,向右的长箭头
  • \impliedby 等价于 \Longleftarrow,向左的长箭头

更复杂的箭头关系可以使用绘制交换图的 tikz-cd 宏包实现。

等号/箭头加文字

在等号上面加一点符号(例如问号)可以使用 \overset,例如

1
\overset{?}{=}

在等号上下加入更多文字,可以使用 \xlongequal[] 包裹的内容在等号下方,{} 包裹的内容在等号上方,等号会根据上下标的长度自动调整长度

1
\xlongequal[aaa]{bbb}

与之类似的,还有支持上下标的箭头,可以使用 \xleftarrow\xrightarrow 实现,例如

1
\xleftarrow[aaa]{bbb}

符号上下标

下图整理了常见的在字母正上方和正下方所采用的特殊标记。

制表源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
\begin{table}
\centering
\begin{tabular}{|c|c|c|c|}
\hline
\textbf{功能} & \textbf{命令} & \textbf{示例} \\
\hline
横线 & \verb|\bar{a}| & $\bar{a}$ \\
长横线(上) & \verb|\overline{xyz}| & $\overline{xyz}$ \\
长横线(下) & \verb|\underline{xyz}| & $\underline{xyz}$ \\
波浪线 & \verb|\tilde{a}| & $\tilde{a}$ \\
长波浪线 & \verb|\widetilde{xyz}| & $\widetilde{xyz}$ \\
帽子 & \verb|\hat{a}| & $\hat{a}$ \\
长帽子 & \verb|\widehat{xyz}| & $\widehat{xyz}$ \\
一个点 & \verb|\dot{a}| & $\dot{a}$ \\
两个点 & \verb|\ddot{a}| & $\ddot{a}$ \\
向量箭头 & \verb|\vec{a}| & $\vec{a}$ \\
自定义符号 & \verb|\overset{x}{a}| & $\overset{\sim}{a}$ \\
\hline
\end{tabular}
\end{table}

同时使用上下标时,P^b_c(效果为 \(P^b_c\))可能导致上下标不对齐,可以加上 {} 改为 P{}^b_c(效果为 \(P{}^b_c\)

矩阵

表示矩阵所有元素的一种直接的方式是基于 array 环境,例如

1
2
3
4
5
6
7
8
\[
\left(
\begin{array}{cc}
a & b \\
c & d
\end{array}
\right)
\]

更常见的做法是使用专门的矩阵环境:pmatrix(小括号),bmatrix(大括号),还有一个不常见的 matrix(无括号)。

例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
\[
A = \begin{bmatrix}
a_{11} & a_{12} & \cdots & a_{1n} \\
a_{21} & a_{22} & \cdots & a_{2n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{m1} & a_{m2} & \cdots & a_{mn}
\end{bmatrix}
\]

\[
A = \begin{pmatrix}
a_{11} & a_{12} & \cdots & a_{1n} \\
a_{21} & a_{22} & \cdots & a_{2n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{m1} & a_{m2} & \cdots & a_{mn}
\end{pmatrix}
\]

\[
A = \begin{matrix}
a_{11} & a_{12} & \cdots & a_{1n} \\
a_{21} & a_{22} & \cdots & a_{2n} \\
\vdots & \vdots & \ddots & \vdots \\
a_{m1} & a_{m2} & \cdots & a_{mn}
\end{matrix}
\]

实际排版中,几种省略号很常见:

  • \cdots:(水平居中)省略号;
  • \vdots:竖直省略号;
  • \ddots:对角省略号。

在矩阵的表示中,矩阵的转置(和共轭转置)并没有一个统一的实现方式,常见的几种做法及效果如下

个人倾向于在简单情况下使用 A^\top,不过在实际写作时可以先用 A^T 代替,在整理时进行批量替换即可。

或者使用如下自定义的转置和共轭转置命令

1
2
\newcommand{\trans}{\mathsf{T}}
\newcommand{\hermite}{\mathsf{H}}

参考 What is the best symbol for vector/matrix transpose?

矩阵集合 \(\mathbb{R}^{m \times n}\) 作为一个高频使用的数学符号,可以用如下自定义命令进行简单的封装

1
\newcommand{\mat}[2]{{\mathbb{R}^{#1 \times #2}}}

使用时只需要传递两个维数

1
2
3
\[
\mat{m}{n}
\]

公式高亮盒子

tcolorbox 宏包提供了一些公式高亮的预设环境,例如 \tcboxmath\tcbhighmath(作为前者的特例),效果例如

实现方式如下

1
2
3
4
5
6
\[
\tcboxmath[colframe=orange,colback=white]{\mathcal{K}_{k} = \mathcal{K}_{k+1} = \cdots}
\]
\[
\tcbhighmath{\mathcal{K}_{k} = \mathcal{K}_{k+1} = \cdots}
\]

\tcbhighmath 的默认样式可以通过 \tcbset 命令修改,将其放在导言区即可。

1
\tcbset{highlight math style={enhanced, colframe=blue!40,colback=yellow!20,arc=4pt,boxrule=1pt}}

字体细节

\(\ell\)\ell)是一个手写体的小写字母 l (L小写),通常用于数学公式中替代 l (L小写) 作为下标使用,防止与 1 (数字1) 和 I (大写i) 的混淆。

在排版考究的场合中,一个积分公式需要注意两处细:dx 的字体以及 dx 前面的小间距,例如

1
\int_a^b f(x)\,\mathrm{d}x

虚数单位除了直接使用 i,也可以使用正体的 \mathrm{i} ,后者是一种看起来更正式的做法。

可以使用下面的命令来(重新)定义正体的 \d\i

1
2
\renewcommand{\d}{\,\mathrm{d}}
\renewcommand{\i}{\mathrm{i}}

符号细节

\subset 是(集合)包含于符号,左侧是右侧的子集。一些变体包括带等号的 \subseteq 和带不等号的 \subsetneq,还有一个常用于紧嵌入的 \Subset。将sub换成sup则表示包含符号,右侧是左侧的子集。

1
2
\subset, \subseteq, \subsetneq, \Subset,
\supset, \supseteq, \supsetneq, \Supset,

交集使用 \cap(矩形版本 \sqcap),并集使用 \cup(矩形版本 \sqcup,通常表示不相交的并集)。

mathtools 宏包提供了 \coloneqq 命令,效果可能比直接使用 := 更好一点,但我没看出来。

对于省略号,应该使用 \dots 而非连续的 ...,也可以具体指定下对齐的 \ldots 或居中的 \cdots\dots 会根据具体情况调整(不是直接根据行内/行间公式,还要参考两侧的内容)。

在集合的定义中,应该使用 \mid 而非直接的 |,它可以提供更合适的间距。

对于小于等于号有很多写法,例如 \le,\leq,\leqslant,最后一个不等号的横线是倾斜的,可以用下面的命令用倾斜的不等号 \(\leqslant\) 覆盖默认的不等号 \(\le\)

1
2
3
4
\renewcommand{\le}{\leqslant}
\renewcommand{\leq}{\leqslant}
\renewcommand{\ge}{\geqslant}
\renewcommand{\geq}{\geqslant}

默认的花体的实部虚部符号 \(\Re\)\(\Im\) 很丑,可以用自定义的实部虚部符号替换

1
2
\renewcommand{\Re}{\operatorname{Re}}
\renewcommand{\Im}{\operatorname{Im}}

数学字体

字体命令

下面几个命令是 LaTeX 默认支持的数学环境中的字体:

  • \mathnormal{}:数学环境的默认字体,与正文中相比,字母的间距更大一些,其它几个字体的间距则与正文基本一致(但没有连字),例如 $xyz$$\mathit{xyz}$ 的间距不同。
  • \mathrm{}:罗马体
  • \mathit{}:意大利体(italic),通常是斜体
  • \mathbf{}:粗体(bold),通常是直立的粗体,加粗英文字母与数字
  • \mathsf{}:无衬线体
  • \mathtt{}:打字机体
  • \mathcal{}:手写体(花体),注意默认情形仅支持大写英文字母,某些大写希腊字母不支持
  • \mathbb{}:(需要 amssymb 宏包或 amsfonts)黑板粗体(blackboard bold),注意仅支持大写字母

这些字体命令的实际效果都与实际使用的字体有关。

在正文斜体的定理环境的公式环境里,对公式中的文字使用 \text{xxx} 仍然无法起到正体的效果,可以改成使用 \mathrm{xxx} 或者其他字体。

下面重点讨论一下字体的加粗:

  • \mathbf{} 提供的是加粗直立的大写英文字母,不保证对希腊字母的加粗效果,与当前字体配置有关。
  • \boldsymbol{} 可以生成倾斜的粗体。
  • 上述两种方案的原理都是通过改变字体系列来加粗,但是并不是所有符号都有粗体版本。更好的方案是使用 bm 宏包提供的 \bm{} 命令来获得加粗符号,它通过更底层的 TeX 低级命令动态构造加粗字形,因此能对任意符号、表达式、上下标都正确加粗。
  • 除此之外,对于正文字体的加粗还有 \textbf\bfseries 以及一个已经废弃的 \bf 命令,注意不要混用。

举一个例子

1
2
3
4
5
6
7
8
9
10
\documentclass{article}
\usepackage{amsmath, amssymb}

\begin{document}

$\mathbf{\lambda}, \mathbf{\Lambda}$

$\bm{\lambda}, \bm{\Lambda}$

\end{document}

当前英文文档可以正确显示两个希腊字母的加粗,但是改成 ctexart 或导入 ctex 宏包就会因为字体原因使得 \mathbf 加粗大写 Lambda 无法显示,并且产生警告。

即使是这样,markdown 渲染以及编辑器提供的公式预览仍然是正常的,这导致类似的错误非常隐蔽。 与 LaTeX 环境不同,markdown 的公式渲染可能并不支持 bm 宏包,这与具体的 markdown 环境有关,在 markdown 中还是最好使用 \mathbf 来加粗。

英文字母

英文大小写字母的常见字体效果如图

\mathcal{} 是 LaTeX 直接提供的花体命令,而 mathrsfs 宏包提供了一套略微不同的花体,使用\mathscr{}命令即可,它提供的花体更花哨复杂一些。

除此之外,还有一种可读性最差的哥特体(mathfrak),并不需要额外的宏包,直接使用\mathfrak{}命令即可

每次看到这玩意我都得查表才知道它到底是什么字母。

可以用自定义命令定义不同字体的字符,使得数学公式的编写更加简洁,尤其在某些特殊字体的符号需要大量使用时,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
\newcommand{\cA}{\mathcal{A}}
\newcommand{\cB}{\mathcal{B}}
\newcommand{\cC}{\mathcal{C}}
\newcommand{\cD}{\mathcal{D}}
\newcommand{\cE}{\mathcal{E}}
\newcommand{\cF}{\mathcal{F}}
\newcommand{\cG}{\mathcal{G}}
\newcommand{\cH}{\mathcal{H}}
\newcommand{\cI}{\mathcal{I}}
\newcommand{\cJ}{\mathcal{J}}
\newcommand{\cK}{\mathcal{K}}
\newcommand{\cL}{\mathcal{L}}
\newcommand{\cM}{\mathcal{M}}
\newcommand{\cN}{\mathcal{N}}
\newcommand{\cO}{\mathcal{O}}
\newcommand{\cP}{\mathcal{P}}
\newcommand{\cQ}{\mathcal{Q}}
\newcommand{\cR}{\mathcal{R}}
\newcommand{\cS}{\mathcal{S}}
\newcommand{\cT}{\mathcal{T}}
\newcommand{\cU}{\mathcal{U}}
\newcommand{\cV}{\mathcal{V}}
\newcommand{\cW}{\mathcal{W}}
\newcommand{\cX}{\mathcal{X}}
\newcommand{\cY}{\mathcal{Y}}
\newcommand{\cZ}{\mathcal{Z}}

\newcommand{\RR}{\mathbb{R}}
\newcommand{\CC}{\mathbb{C}}
\newcommand{\QQ}{\mathbb{Q}}

希腊字母

LaTeX 对希腊字母的默认支持不完整,有的字母有大小写,有的字母只有小写,有的甚至完全不支持(omicron), 有的还有 var 开头的变体,如下表。希腊字母通常不会使用花体之类的变形。如果使用额外的字体宏包,则可能支持的范围更大一些。

omicron 在 LaTeX 中没有对应的符号 \omicron,因为它的大小写和英文字母Oo完全一样。 同理也没有大写的 \Alpha\Beta,因为和英文字母 A B 完全一样。

自定义命令

梳理一下各种自定义(重定义)命令的用法,LaTeX 以及各种宏包都提供了很多相似功能的命令。

不建议大量使用自定义命令,因为这会导致 LaTeX 代码片段难以迁移复用,换一个环境无法通过编译。

LaTeX 提供的引入新命令的宏定义,使用方法如下

1
\newcommand{\<name>}[<nargs>][<default>]{<definition>}

它支持几种使用方式:不带参数,带一个或多个参数必选参数,还支持一个可选参数,此时需要提供参数默认值。

在不带参数时会直接进行整体替换,例如

1
2
3
4
5
\newcommand{\R}{\mathbb{R}}

\[
x \in \R.
\]

如果带参数,定义时需要指明参数个数(最多9个),形式为

1
\newcommand\cmd[参数个数]{命令的定义}

在命令的定义中使用 #1 引用第一个参数,#2 引用第二个参数,以此类推,在使用时则使用{}分别包裹每一个参数(类似\frac{}{}),例如

1
2
3
4
5
\newcommand{\inner}[2]{\langle #1, #2 \rangle}

\[
\inner{x}{y}
\]

LaTeX 允许第一个参数携带默认值,此时必须使用{}传递后续参数,第一个参数如果不使用默认值则需要使用[]传递,例如

1
2
3
4
5
6
7
8
9
\newcommand{\demo}[3][2]{#1+#2+#3}

\[
\demo{10}{20}
% 2 + 10 + 20

\demo[10]{20}{30}
% 10 + 20 + 30
\]

\newcommand 的参数允许含有空行,例如

1
2
3
4
5
6
7
8
9
\newcommand{\block}[1]{%
\begin{quote}
#1
\end{quote}
}

\block{This is paragraph 1.

This is paragraph 2.}

它的变体 \newcommand* 则不允许参数含有空行,适合用于定义数学命令、行内短命令。

LaTeX 不允许定义一个已经存在的命令,必须使用 \renewcommand 覆盖原本定义,用法与 \newcommand 类似,例如

1
\renewcommand{\le}{\leqslant}

除此之外,还有一个更加灵活的 \providecommand:在命令未定义时会进行定义,如果命令已经定义,则保留原样,不会用新定义覆盖。

\newcommand 这些接口的设计在实际使用时非常不方便, xparse 宏包提供了对应的现代化接口 \NewDocumentCommand 等,用于取代传统的 \newcommand,但是实际使用也更加复杂。

1
\NewDocumentCommand\<name>{<arg spec>}{<definition>}

xparse 宏包已经被现代 LaTeX 内核默认集成,不需要用户手动导入。

自定义运算符

整理一下 LaTeX 自定义运算符的各种方式,自定义运算符相比于数学公式中的普通符号,最大的区别是上下标的位置,通常我们要求运算符的上下标在行间公式中直接位于正上方和正下方,在行内公式中则位于右上右下。

LaTeX 还提供了更精细的 \limits\nolimits 命令来调整上下标的两种位置。

基础

第一种方式是基于 \mathop 命令,通常结合 \mathrm 调整为罗马字体。

1
2
3
\[
\mathop{\mathrm{max2}}_i \{x_i\}
\]

可以使用 \newcommand* 将其封装一下,便于重复使用

1
2
3
4
5
\newcommand*{\max2}{\mathop{\mathrm{max2}}}

\[
\max2_i \{x_i\}
\]

第二种方式是基于 amsmath 的 \operatorname 命令(调用 amsopn 包实现),使用例如

1
2
3
4
\[
\operatorname{max3}_i^j\{x_i\}
\operatorname*{max3}_i^j\{x_i\}
\]

这里存在两个版本:\operatorname 版本的上下标始终在右上右下角,\operatorname* 版本则会根据行间公式和行内公式自动调整。

amsmath 预先定义了大量数学符号,与基于 \operatorname\operatorname* 定义出来的效果是一样的。

我们可以用 \newcommand\operatorname 封装为新命令,但是 amsmath 已经提供了更方便的基于 \operatorname/\operatorname* 打包的新命令 \DeclareMathOperator/\DeclareMathOperator*,使用例如

1
2
\DeclareMathOperator{\max3}{max3}
\DeclareMathOperator*{\max3}{max3}

下面是一些临时使用自定义运算符的例子

1
2
3
4
\[
r = \operatorname{rank}(B),
x^* = \mathop{\mathrm{arg\,min}}_{x \in X} f(x)
\]

下面是一些持续性定义新运算符的例子(对于不使用上下标的运算符,用不用星号版本没区别)

1
2
3
4
5
\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator{\diag}{diag}

\DeclareMathOperator*{\argmax}{arg\,max}
\DeclareMathOperator*{\argmin}{arg\,min}

成对分隔符

可以通过如下方式定义成对分隔符命令

1
2
\newcommand*\inner[1]{\langle#1\rangle}
\newcommand*\norm[1]{\lVert#1\rVert}

使用例如

1
2
3
\[
\inner{x,y}, \norm{\frac{1}{x}}
\]

但是这种方式实际并不方便,因为它无法自动调整分隔符的大小。

mathtools 宏包提供了一个更方便 \DeclarePairedDelimiter 命令,例如

1
2
\DeclarePairedDelimiter{\norm}{\lVert}{\rVert}
\DeclarePairedDelimiter{\inner}{\langle}{\rangle}

此时会同时提供 \norm\norm* 命令,后者相当于在符号两侧加上 \left\right,从而实现分隔符大小的自动调整。

1
2
3
\[
\norm*{\frac{1}{x}}
\]

下面是一些定义成对分隔符的粒子

1
2
3
4
5
6
7
8
\DeclarePairedDelimiter{\abs}{\lvert}{\rvert}       % 绝对值
\DeclarePairedDelimiter{\ceil}{\lceil}{\rceil} % 上取整
\DeclarePairedDelimiter{\floor}{\lfloor}{\rfloor} % 下取整
\DeclarePairedDelimiter{\inner}{\langle}{\rangle} % 内积
\DeclarePairedDelimiter{\norm}{\lVert}{\rVert} % 范数
\DeclarePairedDelimiter{\set}{\{}{\}} % 集合 { ... }
\DeclarePairedDelimiter{\paren}{(}{)} % 圆括号 (...)
\DeclarePairedDelimiter{\bracket}{[}{]} % 方括号 [...]