amsmath / AMSFonts

\usepackage{amsmath} 不是一行只做加法的命令。它也做减法。 一旦载入 amsmath,LaTeX 的 \[ 就会被 equation* 环境取代,equationcases 被重新定义,源自 plain TeX 的 \pmatrix 会直接报错,\over 则开始发出警告。所以它不是「便利功能的合集」,而是 数学排版规矩的整体替换。本页讲这次替换的内容,以及跨环境通用的命令——\DeclareMathOperator\text\intertext\substack\dfrac。对齐环境本身另有专页。

载入 amsmath 后到底改变了什么

首先,amsmath 不是单个包,而是一个 合集amsmath.sty 开头附近有三行 \RequirePackage,把 amstext(在公式中排文字的 \text)、amsbsy(数学粗体 \boldsymbol)和 amsopn\DeclareMathOperator 及算子名机制)一并带进来。所以写一行,本页出现的命令就都齐了。

latex
\usepackage{amsmath}

接着是替换。amsmath.sty最后两行\DeclareRobustCommand{\[}{\begin{equation*}}\DeclareRobustCommand{\]}{\end{equation*}}——也就是说,陈列公式的基本命令本身被换成了 amsmath 的环境。同一个文件里,equationcasesmatrixpmatrix 都经过 \renewenvironment\nonumber 也被重新定义。正是因为有这些替换,\tag\qedhere 和编号的自动避让才能工作。反过来,写 $$$$ 会绕开这一层,amsmath 的机制也就一并失效。

也有被拿走的东西。把 plain TeX 的写法直接带进来就会卡住。$\pmatrix{a&b\cr c&d\cr}$ 会得到 ! Package amsmath Error: Old form \pmatrix should be \begin{pmatrix}.\cases{…} 也会被同样地训一顿。1 \over 2 仍能通过,但会附带 Package amsmath Warning: Foreign command \over; \frac or \genfrac should be used instead。把旧稿改用 amsmath 时,最先冒出来的就是这三条,而它们说的是同一件事:换用新写法。

amsmath 之所以能这样大动干戈,是因为它被归类为 LaTeX 的 required 包。随附的 README 写明,amsmath 的维护自 2016 年起从 AMS 移交给 LaTeX Project——amsmath.sty 的版权声明写着「2016–2023 LaTeX Project and American Mathematical Society」,并指明当前维护者是 LaTeX Project。实际上它就是 LaTeX 本体的一部分,这正是它可以替换标准命令的原因。

\DeclareMathOperator:算子名为什么不能写成斜体

在数学模式里字母就是变量,所以敲 rank A 得到的是 r、a、n、k、A 的乘积。LaTeX 预先定义了 \sin\log\lim 等数十个算子名,但 rank 不在其中。你也许以为用 \mathit{rank} 去掉斜体就行了。不行:只改字形改不了间距。量一量看。\operatorname{rank} ArankA 之间留出 1.66pt。\mathit{rank} A 只有 1.07pt——那只是意大利体校正,作为算子的间距是零。至于 \mathrm{log} x,直接输出成挤在一起的「logx」。

打开 amsopn.sty,一行就说明了原因。\operatorname 展开为 \mathop{…\operator@font…}。也就是说,算子名不只是一串正体字符,而是被登记为 TeX 符号类别中的 算符(Op)原子。TeX 的间距表在 Op 与 Ord 之间插入 \thinmuskip(3mu)——\log x 里「log」和「x」之间的空隙正是这么来的。\mathrm 只改变字母的字形,原子类别仍是 Ord,于是不会产生空隙。\DeclareMathOperator 不是修饰外观的工具,而是声明含义的工具。

latex
% in the preamble
\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator*{\argmax}{arg\,max}

% in the body
\[
  \rank A \le n, \qquad
  \hat{x} = \argmax_{x \in S} f(x)
\]

只用一次的话 \operatorname{rank} A 就够了;反复使用的算子则应在导言区给它起个名字。有没有星号决定下标的位置。 无星号时下标在右下角,与 \log 相同;有星号时在 正下方,与 \lim\sup\max 相同(处于陈列样式时)。对上例实测:\argmax_{x \in S}x ∈ S 居中位于「arg max」正下方,而 \rank_{k}k 在「rank」右下角。注意 \DeclareMathOperator 只能用于导言区:在正文中使用会得到 ! LaTeX Error: Can be used only in preamble.,随后那个从未被定义的命令还会引发 ! Undefined control sequence.

如果觉得定义里的 \, 有点怪,看看 AMS 自己怎么写。amsopn.sty\limsup 定义为 lim\,sup\liminf 定义为 lim\,inf\injlim 定义为 inj\,lim。用细空格连接算子名的两个词,正是 AMS 的规矩,arg\,max 不过是照办。\operatorname 还有一项隐藏工作:它会临时改写参数内 -.:/* 的数学代码,好让 连字符印成真正的连字符而不是减号。实测中,\operatorname{ess-sup} 输出为一个词「ess-sup」,而 \mathrm{ess-sup} f 输出为「ess − sup f」——减号两侧各有 2.22pt 的二元运算符间距,含义和外观都变了。

\text\mathrm\mbox 该用哪个

把正体字母放进公式有三种办法,各自回答不同的问题。\text{…}(来自 amstext)插入的是「文句」。 内容以正文字体和正文间距排版,敲的空格也会保留——\text{for all } 末尾的空格确实会出现在输出里。\mathrm{…} 让「数学符号」变成正体。 其内部仍处于数学模式,所以空格会消失;它适用于要写成正体的 符号,比如微分的 \mathrm{d}x 或单位。\mbox{…} 是通用的「装进盒子」,本来就不是为数学设计的。

latex
\[
  f(x) = x^2 \quad \text{for all } x \in \mathbb{R},
  \qquad v_{\text{max}} = 3,
  \qquad \int f(x)\,\mathrm{d}x.
\]

\text 胜过 \mbox 的地方在于它 会跟随周围的尺寸amstext.sty 中的定义用 \mathchoice 为陈列、文本、上下标、二级上下标四种语境各分配一个字号。上例中 v_{\text{max}} 的「max」量得高 6.19pt——上下标字号;换成 \mbox{max} 则是 8.85pt,以正文大小赖在下标里。还有一个实用性质:\text 在文本模式中被调用时会退回 \mbox,因此在不确定会以哪种模式展开的宏里使用也很安全。

\intertext\substack:插入而不破坏对齐

想在 align 中间插一行说明——如果先关掉环境、写好句子、再重新打开,前后的对齐位置就会错开。\intertext{…} 解决了这个问题。实测中,被 \intertext 隔开的 align 里,上下两行的 = 都落在横向 291.11pt 处,而插入的句子则作为从左边距开始的普通段落排版。原理很简单:amsmath.sty 里的 \intertext\noalign 内部吐出「下方间距 + 装着文字的 \vbox + 上方间距」。也就是说,文字 从未离开这张对齐表,各列的位置因此保持不变。在对齐环境之外使用会得到 ! Package amsmath Error: Invalid use of \intertext.

latex
\begin{align}
  A &= B + C \\
  \intertext{expanding $C$ gives}
  A &= B + D + E
\end{align}

\[
  \sum_{\substack{0 \le i \le m \\ 0 < j < n}} a_{ij}
\]

\substack{…} 是更小的工具,思路相同。它把 多行条件堆叠 在求和、乘积这类大型算子下方,行用 \\ 分隔。上例中「0 ≤ i ≤ m」和「0 < j < n」成为两行,实测也确认两行都在求和号下方居中堆叠。其内部仍是数学模式,\le 等关系符号照常可用。若想让各行左对齐而不是居中,可用几乎相同的 subarray 环境并传入 l 之类的对齐字母。

\dfrac\binom\boldsymbol:不随语境改变的写法

\frac 本身是标准 LaTeX,但它的大小取决于所处的语境。amsmath 补上了 无视语境的版本\dfrac{…}{…} 永远是陈列样式(大),\tfrac{…}{…} 永远是文本样式(小)。正文中的分数要看得清就用 \dfrac,陈列公式里某一部分要缩小就用 \tfrac。层层相套的连分数可用 \cfrac{…}{…},无论多深每一层都保持可读大小。二项系数是 \binom{n}{k},其固定样式版本为 \dbinom\tbinom

latex
\[
  \binom{n}{k} = \dfrac{n!}{k!\,(n-k)!},
  \qquad \boldsymbol{\nabla} \cdot \boldsymbol{E} = \rho / \varepsilon_0.
\]

\boldsymbol 放在同一节是有原因的。物理与向量分析里常常要把字母加粗,但 \mathbf{E} 给出的是 正体 粗体,而且对希腊字母无效。来自 amsbsy(由 amsmath 一并带来)的 \boldsymbol{E}保持斜体再加粗,对符号也有效,例如 \boldsymbol{\nabla}。若你所在领域把向量写成粗斜体,就用 \boldsymbol;若把矩阵和张量写成正体粗体,就用 \mathbf——按领域惯例选择。把公式编号与节编号绑定的 \numberwithin{equation}{section} 同样出自 amsmath,但编号相关的话题留给「陈列、对齐与编号的公式」那一页。

amssymb 与 AMSFonts:负责添符号的伙伴

分工很清楚:amsmath 增加 排版机制,amssymb 增加 可以写出的符号。amssymb 定义了 AMS 符号字体 msammsbm 中的全部符号,让标准 LaTeX 中没有的数百个字形触手可及——\leqslant\geqslant(斜置不等号)、\nleq\subsetneq\therefore\because\square\blacksquare\varnothing 等。它内部会加载 amsfonts,所以你不必再单独写 amsfonts

latex
\usepackage{amssymb}

\[
  \mathbb{R} \subset \mathbb{C}, \qquad
  \mathfrak{g} = \operatorname{Lie}(G)
\]

AMSFonts 还带来两套数学字母表:通过 \mathbb{…}黑板粗体,以及通过 \mathfrak{…}Fraktur。这里有一个会悄无声息出事的坑:黑板粗体只有大写字母,而且 \mathbb{k} 并不会报错。查看 amssymb.sty 会发现 AMSb 字体的位置 "6B 被分配给了 \daleth;真去编译,出来的不是小写 k,而是 希伯来字母 daleth ℸ。如果需要黑板粗体的小写 k,请使用专门准备的 \Bbbk。Fraktur 则大小写齐全,所以 \mathfrak{g} 表示李代数、\mathfrak{p} 表示素理想都可以随意书写。

导言区应写的三行

任何含数学内容的文档,都应把下面三行放在一起:amsmath(排版机制)、amssymb(符号以及黑板粗体与 Fraktur),以及用于定理与证明的 amsthm。顺序大体自由,但 amsthm 要放在 amsmath 之后,因为像 \qedhere 这样的功能会伸手改动 amsmath 的陈列结构。

document.tex
\documentclass{article}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{amsthm}
\begin{document}
\[
  \zeta(s) = \sum_{n=1}^{\infty} \frac{1}{n^{s}}, \qquad s \in \mathbb{C}
\]
\end{document}
宏包作用主要提供内容
amsmath数学排版机制对齐环境、\text\operatorname\dfrac\binom\boldsymbol
amssymb符号与数学字母表msam、msbm 的数百个符号,\mathbb\mathfrak(自行加载 amsfonts)
amsfonts仅字体\mathbb\mathfrak(不含额外符号)
amsthm定理与证明环境\newtheoremproof 环境、\theoremstyle\qedhere

amsmath 还提供矩阵环境(pmatrixbmatrix 等)和自动调整大小的定界符,但这些分别属于「矩阵与数组」和「求和、积分与大型算子」页面。最后一件事:由于 amsmath 的陈列环境把内容 作为一个宏参数整体读入,其中若有空行就会报错。AMS 的技术说明指出,这套多趟处理算法继承自 Michael Spivak 的 amstex.tex——1980 年代的 AMS-TeX,至今仍以「禁止空行」这条规则的形式活着。