LaTeX 数学公式与字体
整理一下 LaTeX 关于数学公式、数学字体以及相关的细节内容。
AMS 宏包
AMS 提供了一系列最常用的 LaTeX 数学宏包:
amsmath宏包:- 提供了一套增强的数学排版命令和环境,使得数学公式的编辑和排版更加灵活和方便。
- 引入了一些新的数学环境,例如
align和gather,以便更好地控制多行公式的排版。 - 提供了诸如
\text,\DeclareMathOperator等命令,用于在数学模式中插入文本或定义新的运算符。
amssymb宏包:扩展了amsmath,提供了额外的数学符号,如各种箭头、关系符号、集合符号等。amsfonts宏包:提供了一些额外的字体,例如\mathbb命令用于黑板粗体字母。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 X,Section 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}
这里的使用 ={} &
是为了在对齐时产生更合适的间距。(对于一些无参数的命令,也可以加上
{} 来产生合适间距,例如 \sin{}\alpha)
对于多组公式的对齐,例如两行三列的公式可以如下表示,其中公式之间和等号旁都要加上
& 1
2
3
4\begin{align}
a & =1 & b & =2 & c & =3 \\
d & =-1 & e & =-2 & f & =-5
\end{align}
对多行公式的引用,在需要引用的公式最后加上
\label即可,在不需要的公式后面可以加上
\notag,例如 1
2
3
4\begin{align}
a & = b + c \label{eq:1} \\
d & = e + f \notag
\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}
有时我们不希望每一行公式都占用一个单独的编号,而是按照
(3a)、(3b) 的形式进行编号,可以使用
subequations 环境实现,例如 1
2
3
4
5
6\begin{subequations}\label{eq:main}
\begin{align}
a &= b + c \label{eq:main-1} \\
d &= e - f \label{eq:main-2}
\end{align}
\end{subequations}

align、align* 和 aligned
环境总是需要考虑对齐的标记放置,在使用比较麻烦,而且某些情况下的排版不够美观。
还有一组使用更简单的多行公式环境:gather、gather*
和 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}
也可以用定界符括号 \left\{ \right. 手动实现
1
2
3
4
5
6
7
8\begin{equation}
\left\{
\begin{aligned}
a & = b + c \\
c & = d + e
\end{aligned}
\right.
\end{equation}
上下括号
对于长等式的一个常见需求是把其中一部分记作一个新记号,即在一部分项的上下方使用上括号(\overbrace{}^{})和下括号(\underbrace{}_{})。

对应源码为 1
2
3
4\[
\underbrace{a + \overbrace{b + \dots + e}^{A_0} + f}_{A}
+ \underbrace{g + \dots + z}_{B} = 0
\]
有时这里的标注字体过小,可以使用 \mathlarger
命令将公式整体放大,例如 1
2
3\[
\underbrace{a+b+c}_{\mathlarger(A)}
\]
竖向等号
有时存在一些简单的竖向公式排版的需求,下面提供两个例子作为参考。
参考 vertical and horizontal equations,更复杂的情况建议使用 tikz。
基于 array 实现多行对齐,基于 \rotatebox
实现符号的旋转 1
2
3
4
5
6
7
8
9
10
11\usepackage{graphicx}
\[
k_0 := \Vert \bm{k}_0 \Vert
= \begin{array}[t]{@{}c@{}}
\Vert \bm{k} \Vert \\
\rotatebox[origin=c]{90}{$=$} \\
k
\end{array}
=\frac{2\pi}{\lambda}
\]

1 | \usepackage{graphicx} |

公式高亮
对于复杂公式,可以使用几种不同的颜色进行强调,例如 1
2
3
4
5
6
7
8
9
10
11
12
13
14\begin{equation}
\rho
\left(
\frac{\partial \mathbf{u}}{\partial t}
+
{\color{Bittersweet}\mathbf{u}\cdot\nabla \mathbf{u}}
\right)
=
-{\color{OliveGreen}\nabla p}
+
{\color{Orange}\mu \nabla^2 \mathbf{u}}
+
{\color{RoyalBlue}\mathbf{f}}
\end{equation}

在数学公式环境(包括行内和行间公式)可以使用 \boxed
命令给公式添加方框,通常会给整体添加方框,例如 1
2
3
4
5
6
7
8
9
10We have $\boxed{a^2 + b^2 = c^2}$ in the Pythagorean theorem.
\[
\boxed{a^2 + b^2 = c^2}
\]
\begin{gather}
\rho \left( \frac{\partial \bm{v}}{\partial t} + (\bm{v} \cdot \nabla) \bm{v} \right)
+ \nabla p = \mu \nabla^2 \bm{v} + \bm{f}. \\
\boxed{\nabla \cdot \bm{v} = 0}
\end{gather}
效果如下

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}}
在
align环境中使用时,要注意不能包括&,否则会报错。
数学符号
定界符
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|,否则竖线的尺寸无法随之进行自适应调整。例如在复杂的集合表示中

对应源码如下 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15\[
\mathcal{T} =
\left\{ \bm{X} \in \mathbb{R}^{m \times n} \middle| \bm{X} =
\begin{bmatrix}
\bm{U} \\ \bm{U}^\perp
\end{bmatrix}
\begin{bmatrix}
\mathbb{R}^{r \times r} & \mathbb{R}^{r \times (n-r)} \\
\mathbb{R}^{(m-r) \times r}
\end{bmatrix}
\begin{bmatrix}
\bm{V} & \bm{V}^\perp
\end{bmatrix}
\right\}
\]
有时我们对自动生成的定界符大小不满意,或者公式块必须要换行,可以使用
\big(1.5倍)、\Big(2倍)、\bigg(2.5倍)、\Bigg(3倍)
等命令进行手动调节,这些命令只作用于一个定界符,不需要成对。
上下标
下图整理了常见的在字母正上方和正下方所采用的特殊标记。

制表源码 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\))
箭头
LaTeX 提供了大量的箭头相关的命令,amsmath
又为其提供了更多支持,如下表。


其中几个常用的箭头有缩写指令:(至少肉眼看不出区别)
\to等价于\rightarrow,向右的小箭头\gets等价于\leftarrow,向左的小箭头\iff等价于\Longleftrightarrow,向左向右的长箭头\implies等价于\Longrightarrow,向右的长箭头\impliedby等价于\Longleftarrow,向左的长箭头\leadsto等价于\rightsquigarrow,弯曲的向右箭头
更复杂的箭头关系可以使用绘制交换图的
tikz-cd宏包实现。
在等号上面加一点符号(例如问号)可以使用 \overset 或
\stackrel 命令,例如 1
2
3\[
\overset{?}{=}, \quad \stackrel{\mathrm{def}}{=}
\]

对应源码为 1
2
3\[
a \overset{?}{=} b, \quad \vec{x} \stackrel{\mathrm{def}}{=} (x_1,\ldots,x_n)^\top
\]
在等号上下加入更多文字,可以使用
\xlongequal,[]
包裹的内容在等号下方,{}
包裹的内容在等号上方,等号会根据上下标的长度自动调整长度
1
2
3\[
\xlongequal[aaa]{bbb}
\]
与之类似的,还有支持上下标的箭头,可以使用 \xleftarrow
和 \xrightarrow 实现,例如 1
2
3\[
\xleftarrow[aaa]{bbb}
\]
矩阵表示
表示矩阵所有元素的一种直接的方式是基于 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:对角省略号(左上到右下)\adots:反对角省略号(左下到右上)(需要yhmath宏包)
更复杂的矩阵表示可以使用 nicematrix 宏包,它提供了
NiceMatrix、bNiceMatrix
等环境,可以定制更丰富的矩阵样式,还可以和 tikz 结合。
这里提供一个示例

对应源码如下 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16\[
\begin{bNiceArray}{cw{c}{1cm}cc}[margin]
\Block{3-3}{A} & & & 0 \\
& & & \Vdots \\
& & & 0 \\
0 & \Cdots& 0 & 0
\end{bNiceArray},
\quad
\begin{bNiceArray}{cw{c}{1cm}c|c}[margin]
\Block{3-3}{A} & & & 0 \\
& & & \Vdots \\
& & & 0 \\
\hline
0 & \Cdots& 0 & 0
\end{bNiceArray}
\]
矩阵记号
矩阵集合 \(\mathbb{R}^{m \times n}\)
作为一个高频使用的数学符号,可以用如下自定义命令进行简单的封装
1
\newcommand{\mat}[2]{{\mathbb{R}^{#1 \times #2}}}
使用时只需要传递两个维数 1
2
3\[
\mat{m}{n}
\]
在矩阵的符号表示中,转置(和共轭转置)并没有一个标准或统一的实现方式,常见的几种做法及效果如下

个人倾向于在简单情况下使用
A^\top,不过在实际写作时可以先用 A^T
代替,在整理时进行批量替换即可。
或者使用如下自定义的转置和共轭转置命令 1
2\newcommand{\trans}{\mathsf{T}}
\newcommand{\hermite}{\mathsf{H}}
不常用符号
一些不常用的符号整理如下:
- Dagger (single cross): \(\dag\),
\dag - Double dagger (double cross): \(\ddag\),
\ddag - Star: \(\star\),
\star - Big star: \(\bigstar\),
\bigstar - Heart: \(\heartsuit\),
\heartsuit - Diamond: \(\diamondsuit\),
\diamondsuit - Club: \(\clubsuit\),
\clubsuit - Spade: \(\spadesuit\),
\spadesuit - Large circle: \(\bigcirc\),
\bigcirc - Bullet: \(\bullet\),
\bullet - Circled plus: \(\oplus\),
\oplus - Circled minus: \(\ominus\),
\ominus - Tensor (direct) product: \(\otimes\),
\otimes - Direct sum (binary circled plus): \(\oplus\),
\oplus - Scalar product (dot in circle): \(\odot\),
\odot - Boxed multiplication (circle times variant): \(\boxtimes\),
\boxtimes - Circled asterisk: \(\circledast\),
\circledast
还有几个 Markdown 不支持的符号(但是也不需要额外的宏包)

符号细节
\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\)
很丑,可以用自定义的实部虚部符号 \(\operatorname{Re}\) 和 \(\operatorname{Im}\) 替换 1
2\renewcommand{\Re}{\operatorname{Re}}
\renewcommand{\Im}{\operatorname{Im}}
垂直符号为 \perp,也可以使用
\bot,两者看起来是一样的。
有时希望把复杂公式中的某项划掉,可以使用 cancel
宏包提供的 \cancel 等命令,例如 1
2
3
4\[
\sum_i a_i + \cancel{\sum_i b_i} + \bcancel{\sum_i c_i}
+ \xcancel{\sum_i d_i} + \cancelto{0}{\sum_i e_i}= 0
\]

避免使用有歧义的符号表述,经典的反面例子是:\(\sin^{-1}(x)\)。
数学字体
英文字母
下面是 LaTeX 在数学环境中常见的英文字体:
\mathnormal{}:数学环境的默认字体,与正文中相比,字母的间距更大一些,其它几个字体的间距则与正文基本一致(但没有连字),例如$xyz$和$\mathit{xyz}$的间距不同。\mathrm{}:罗马体\mathit{}:意大利体(italic),带一点倾斜\mathbf{}:粗体(bold),直立粗体\mathsf{}:无衬线体\mathtt{}:打字机体\mathbb{}:(需要amssymb宏包或amsfonts)黑板粗体(blackboard bold),直立空心体,注意默认仅支持大写英文字母\bm{}:(需要bm宏包)粗体,与前面几种基于字符替换的字体不同,它通过更底层的 TeX 低级命令动态构造加粗字形,对任意符号、表达式、上下标都可以正确加粗,不改变原有的字形,建议使用。\mathcal{}:倾斜的手写体(花体),注意默认仅支持大写英文字母\mathfrak{}:哥特体,可读性最差\mathscr{}:(需要mathrsfs宏包)另一种花体
这些字体命令的实际效果如图(\mathbb 和
\mathcal
只支持大写英文字母,对于小写英文字母则会错误显示其它字符)

注:
- 在正文是斜体的定理环境的数学公式中,对文字使用
\text{xxx}仍然无法起到正体的效果,可以改成使用\textnormal{xxx}或者其他字体 \mathbf是直立的粗体,\boldsymbol可以提供倾斜的粗体,但是更建议使用\bm命令进行倾斜加粗。- 在正文中,对字体的加粗还有
\textbf,\bfseries以及一个已经废弃的\bf命令,注意不要混用。
希腊字母
LaTeX 默认对 24 个希腊字母的支持并不完整,有的字母有大小写,有的字母只有小写,有的甚至完全不支持(omicron),可能是考虑到部分字母和英文字母实际上完全一样的原因。此外,部分字母还存在 var 开头的变体,完整表格如下。

对于前文中提到的各种字体命令,(在标准英文文档类中)将其作用在希腊字母上,效果如下表。

测试结果表明:在英文文档中
- 大部分字体效果对大写希腊字母正常;
\mathcal和\mathbb对大写希腊字母无效,会 fallback 显示其它符号; - 绝大部分字体效果对小写希腊字母无效(fallback 到默认字体);
- 绝大部分字体效果对于 var 变体的大小写希腊字母均无效;
\bm对大小写希腊字母以及 var 变体都可以正常加粗,建议使用。
使用额外的字体宏包会影响这里的结果,我们主要关注 ctex 文档类和 xelatex 编译器的方案, 也就是通常的中文文档方案,此时会对希腊字母的支持产生不利影响,测试结果如下。

测试结果表明:在中文文档中(ctex + xelatex),除了默认字体之外
- 除了
\bm的绝大部分字体无法正确显示大写希腊字母:直接消失(警告)或者 fallback 显示其它字符; - 除了
\bm的绝大部分字体对小写希腊字母,以及 var 变体均无效。
数学字体错误
数学公式中的字体在实际使用中有很多潜在问题:如果将某个字体作用在其支持范围之外的字符,可能导致各种结果:
- 可能正确显示;
- 可能直接导致错误;
- 可能产生警告,在正文中直接消失;
- 还可能 fallback 显示其它字符。
如果只显示模糊的字体缺失警告,无法定位具体的问题,可以尝试在文档开头加上
1
\tracinglostchars=3
这会把警告提升为编译错误,从而确定错误所在。
即使在 LaTeX 编译出问题的情况下,Markdown 的渲染以及各种编辑器提供的公式预览可能仍然是完全正常的字体效果,因为它们并不依赖 Tex 引擎,而是采用了基于 JS 的渲染引擎,这导致类似的字体错误非常隐蔽。
一个典型的例子是对小写英文字母使用 \mathbb 和
\mathcal 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16\documentclass{article}
\usepackage{amsmath, amssymb}
\usepackage{verbatim}
\begin{document}
\begin{itemize}
\item \verb|\mathbb{Uu}|: $\mathbb{Uu}$
\item \verb|\mathbb{Ww}|: $\mathbb{Vv}$
\item \verb|\mathbb{Ww}|: $\mathbb{Ww}$
\item \verb|\mathcal{Uu}|: $\mathcal{Uu}$
\item \verb|\mathcal{Ww}|: $\mathcal{Vv}$
\item \verb|\mathcal{Ww}|: $\mathcal{Ww}$
\end{itemize}
\end{document}

这里对小写 \(uvw\)
的加粗和花体实际会 fallback 显示其它符号,因为 \mathbb{} 和
\mathcal{} 只保证了大写英文字母的效果。
自定义字体命令
可以用自定义命令定义不同字体的字符,使得数学公式的编写更加简洁,尤其在某些特殊字体的符号需要大量使用时,例如
1 | \newcommand{\cA}{\mathcal{A}} |
1 | \newcommand{\RR}{\mathbb{R}} |
字体细节
\(\ell\)(\ell)是一个手写体的小写字母
l (L小写),通常用于数学公式中替代 l (L小写) 作为下标使用,防止与 1
(数字1) 和 I (大写i) 的混淆。在某些情况下还会使用 \(\kappa\) (\kappa)代替
k。
可以用下面的命令来定义 \l 和 \k
1
2\renewcommand{\l}{\ell}
\renewcommand{\k}{\kappa}
在排版考究的场合中,一个积分公式需要注意两处细: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}}
注意这几个符号本身已经被定义,被用作重音等符号变体,谨慎使用。
制表源码
这里附上上文中使用的几个表格的完整源码
1 | \documentclass{article} |
自定义命令
梳理一下各种自定义(重定义)命令的用法,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
6\DeclareMathOperator{\rank}{rank}
\DeclareMathOperator{\diag}{diag}
\DeclareMathOperator{\tr}{Tr}
\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}}
\]
这种方式得到的分隔符无法自动调整高度和大小,最好加上
\left 和
\right,例如间断有限元中常用的跳跃和平均可以这样定义
1
2\newcommand*\jump[1]{\left\{\!\left\{#1\right\}\!\right\}}
\newcommand*\mean[1]{\left[\!\left[#1\right]\!\right]}
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
9% \usepackage{mathtools}
\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}{[}{]} % 方括号 [...]
自定义命令整理
汇总一下上文中提到的一些常用符号/运算符定义。
1 | \newcommand{\mat}[2]{{\mathbb{R}^{#1 \times #2}}} |