整理一下 LaTeX 关于数学公式、数学字体以及相关的细节内容。
主要内容参考 一份(不太)简短的 LaTeX2ε 介绍 和《LaTeX 入门(刘海洋)》。
AMS 宏包 AMS 提供了一系列最常用的 LaTeX 数学宏包:
amsmath 宏包:
提供了一套增强的数学排版命令和环境,使得数学公式的编辑和排版更加灵活和方便。
引入了一些新的数学环境,例如 align 和 gather,以便更好地控制多行公式的排版。
提供了诸如 \text, \DeclareMathOperator 等命令,用于在数学模式中插入文本或定义新的运算符。
amssymb 宏包:扩展了 amsmath,提供了额外的数学符号,如各种箭头、关系符号、集合符号等。
amsfonts 宏包:提供了一些额外的字体,例如 \mathbb 命令用于黑板粗体字母。
amsthm 宏包:提供了 theorem, lemma, proof 等定理或证明环境,方便用户在文档中定义和使用定理。
下面的数学公式绝大部分都需要这些宏包,默认已经被导入
1 \usepackage {amsmath, amssymb, amsthm}
这些宏包在实际使用时可能要注意一下导入的顺序关系,例如最好先调用 amsmath 再调用其他几个,amssymb 会自动引入 amsfonts。
数学公式 行内公式直接使用 $...$ 包裹即可,也可以使用 \(...\) 包裹,关于哪一种更好并没有统一的结论,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}
同理可以修改 table 和 figure 环境的编号规则。
可以使用 \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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \usepackage {graphicx}\[ S = \begin {array}[t]{@{}c@{}} A \\ \rotatebox [origin=c]{90}{$ {}=$ } \\ A_ 1 \end {array} + \begin {array}[t]{@{}c@{}} B \\ \rotatebox [origin=c]{90}{$ {}=$ } \\ B_ 1 \end {array} \]
公式高亮 对于复杂公式,可以使用几种不同的颜色进行强调,例如
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 10 We 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 环境中使用时,要注意不能包括 &,否则会报错。
除了简单的公式盒子,还可以利用 tikz 宏包在给数学公式加上背景颜色以及箭头标注,例如 synercys/annotated_latex_equations 。
数学符号 定界符 Latex 提供了多种定界符(主要是括号)表示公式块的边界,包括最基本的三种括号:
小括号 ()
中括号 []
大括号 \{\}(需要转义)(等价于 \lbrace\rbrace)。
尽量避免在 LaTeX 的复杂数学公式中把中括号 [] 和大括号 {} 作为普通括号使用,主要使用各种尺寸的小括号即可。尤其要慎用中括号,因为在数学中有其它的含义,例如取整,容易引起歧义。
此外,还有常用于表示内积的尖括号 \langle\rangle(不是 <>),表示模和范数的单竖线 |(等价于 \vert)以及双竖线 \|(等价于 \Vert)。 这两种竖线命令本身是没有左右(开符号,闭符号)区分的,在实践中更建议用成对版本:(虽然在显示中没什么区别)
1 2 3 \[ \lvert b \rvert , \lVert b \rVert , \]
常见的定界符如下图(表格取自 lshort-zh-cn)
如果定界符的高度不能盖住内部的公式块,看起来非常不舒服,可以使用 \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 又为其提供了更多支持,如下表。(表格取自 lshort-zh-cn)
其中几个常用的箭头有缩写指令:(至少肉眼看不出区别)
\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} \]
巨算符 巨算符是指在显示公式中自动放大的运算符,例如 $$ \sum,\quad \prod,\quad \int,\quad \bigcup,\quad \bigcap $$ 这类符号在 LaTeX 的数学类型系统中属于 \mathop,其特点是可以带上下标,并且在显示公式中上下标通常位于符号的上下方。(对于一般的符号,以及在行内公式中,上下标通常会出现在右上方和右下方)
当巨算符的上下标较长时,可以在上下标内部进行换行。最推荐的做法是使用 \substack,它支持在上下标中直接使用 \\ 进行换行。例如
1 2 3 \sum _ {\substack {i=1\\ i\neq j}}^ {n} a_ {ij},\qquad \sum _ {\substack {1\le i\le n\\ 1\le j\le m}} a_ {ij}.
$$ \sum_{\substack{i=1\ i\neq j}}^{n} a_{ij}, \qquad \sum_{\substack{1\le i\le n\ 1\le j\le m}} a_{ij}. $$
当然,使用更常用的 aligned 和 array 环境也是可行的。
矩阵表示 表示矩阵所有元素的一种直接的方式是基于 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 }}}
使用时只需要传递两个维数
在矩阵的符号表示中,转置(和共轭转置)并没有一个标准或统一的实现方式,常见的几种做法及效果如下
参考 What is the best symbol for vector/matrix transpose?
个人倾向于在简单情况下使用 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,通常表示不相交的并集)。
集合的差可以用 \setminus 或者直接用原始的 \backslash。(\ 是特殊字符,\\ 不能作为 \ 的转义,必须使用完整名称 \backslash)
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}}
垂直符号为 \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)$,这既可以解释为 $\arcsin(x)$,也可以解释为 $1/\sin(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 显示其它字符。
如果只显示模糊的字体缺失警告,无法定位具体的问题,可以尝试在文档开头加上
这会把警告提升为编译错误,从而确定错误所在。
即使在 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 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 \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}}
1 2 3 4 5 6 \newcommand {\RR }{\mathbb {R}}\newcommand {\CC }{\mathbb {C}}\newcommand {\QQ }{\mathbb {Q}}\newcommand {\NN }{\mathbb {N}}\newcommand {\EE }{\mathbb {E}}\newcommand {\TT }{\mathbb {T}}
字体细节 $\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 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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 \documentclass {article}\usepackage {amsmath, amssymb}\usepackage {bm}\usepackage {array}\usepackage {geometry}\usepackage {xcolor}\usepackage {mathrsfs}\usepackage {booktabs}\begin {document}\begin {tabular}{lll} mathnormal & $ ABCDEFGHIJKLMNOPQRSTUVWXYZ$ \\ & $ abcdefghijklmnopqrstuvmxyz0123456789$ \\ [6pt] mathrm & $ \mathrm {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathrm {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathit & $ \mathit {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathit {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathbf & $ \mathbf {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathbf {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathsf & $ \mathsf {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathsf {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathtt & $ \mathtt {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathtt {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathbb & $ \mathbb {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & {\color {red}$ \mathbb {abcdefghijklmnopqrstuvmxyz0123456789}$ } \\ [6pt] bm & $ \bm {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \bm {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathcal & $ \mathcal {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & {\color {red}$ \mathcal {abcdefghijklmnopqrstuvmxyz0123456789}$ } \\ [6pt] mathfrak & $ \mathfrak {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathfrak {abcdefghijklmnopqrstuvmxyz0123456789}$ \\ [6pt] mathscr & $ \mathscr {ABCDEFGHIJKLMNOPQRSTUVWXYZ}$ \\ & $ \mathscr {abcdefghijklmnopqrstuvmxyz0123456789}$ \end {tabular}\newpage \begin {center} \begin {tabular}{l rl rl rl rl} \toprule Name & Uppercase & & Variant & & Lowercase & & Variant & \\ \midrule Alpha & & {\color {cyan}$ A$ } & & & \verb |\alpha | & $ \alpha $ \\ Beta & & {\color {cyan}$ B$ } & & & \verb |\beta | & $ \beta $ \\ Gamma & \verb |\Gamma | & $ \Gamma $ & \verb |\varGamma | & $ \varGamma $ & \verb |\gamma | & $ \gamma $ & & \\ Delta & \verb |\Delta | & $ \Delta $ & \verb |\varDelta | & $ \varDelta $ & \verb |\delta | & $ \delta $ \\ Epsilon & & {\color {cyan}$ E$ } & & & \verb |\epsilon | & $ \epsilon $ & \verb |\varepsilon | & $ \varepsilon $ \\ Zeta & & {\color {cyan}$ Z$ } & & & \verb |\zeta | & $ \zeta $ \\ Eta & & {\color {cyan}$ H$ } & & & \verb |\eta | & $ \eta $ \\ Theta & \verb |\Theta | & $ \Theta $ & \verb |\varTheta | & $ \varTheta $ & \verb |\theta | & $ \theta $ & \verb |\vartheta | & $ \vartheta $ \\ Iota & & {\color {cyan}$ I$ } & & & \verb |\iota | & $ \iota $ & \\ Kappa & & {\color {cyan}$ K$ } & & & \verb |\kappa | & $ \kappa $ & \\ Lambda & \verb |\Lambda | & $ \Lambda $ & \verb |\varLambda | & $ \varLambda $ & \verb |\lambda | & $ \lambda $ & & \\ Mu & & {\color {cyan}$ M$ } & & & \verb |\mu | & $ \mu $ \\ Nu & & {\color {cyan}$ N$ } & & & \verb |\nu | & $ \nu $ \\ Xi & \verb |\Xi | & $ \Xi $ & \verb |\varXi | & $ \varXi $ & \verb |\xi | & $ \xi $ \\ Omicron & & {\color {cyan}$ O$ } & & & & {\color {cyan}$ o$ } & \\ Pi & \verb |\Pi | & $ \Pi $ & \verb |\varPi | & $ \varPi $ & \verb |\pi | & $ \pi $ & \verb |\varpi | & $ \varpi $ \\ Rho & & {\color {cyan}$ R$ } & & & \verb |\rho | & $ \rho $ & \verb |\varrho | & $ \varrho $ \\ Sigma & \verb |\Sigma | & $ \Sigma $ & \verb |\varSigma | & $ \varSigma $ & \verb |\sigma | & $ \sigma $ & \verb |\varsigma | & $ \varsigma $ \\ Tau & & {\color {cyan}$ T$ } & & & \verb |\tau | & $ \tau $ \\ Upsilon & \verb |\Upsilon | & $ \Upsilon $ & \verb |\varUpsilon | & $ \varUpsilon $ & \verb |\upsilon | & $ \upsilon $ & & \\ Phi & \verb |\Phi | & $ \Phi $ & \verb |\varPhi | & $ \varPhi $ & \verb |\phi | & $ \phi $ & \verb |\varphi | & $ \varphi $ \\ Chi & & {\color {cyan}$ X$ } & & & \verb |\chi | & $ \chi $ & & \\ Psi & \verb |\Psi | & $ \Psi $ & \verb |\varPsi | & $ \varPsi $ & \verb |\psi | & $ \psi $ & & \\ Omega & \verb |\Omega | & $ \Omega $ & \verb |\varOmega | & $ \varOmega $ & \verb |\omega | & $ \omega $ & & \\ \bottomrule \end {tabular} \end {center}\newpage \begin {tabular}{lll} mathnormal & $ \Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega $ & (var) $ \varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega $ \\ & $ \alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega $ & (var) $ \varepsilon \vartheta \varpi \varrho \varsigma \varphi $ \\ [6pt] mathrm & $ \mathrm {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \mathrm {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathrm {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathrm {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathit & $ \mathit {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \mathit {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathit {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathit {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathbf & $ \mathbf {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \mathbf {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathbf {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathbf {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathsf & $ \mathsf {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \mathsf {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathsf {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathsf {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathtt & $ \mathtt {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \mathtt {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathtt {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathtt {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathbb & {\color {red}$ \mathbb {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ } & (var) $ \mathbb {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathbb {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathbb {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] bm & $ \bm {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ & (var) $ \bm {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \bm {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \bm {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathcal & {\color {red}$ \mathcal {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ } & (var) $ \mathcal {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathcal {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathcal {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathfrak & {\color {red}$ \mathfrak {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ } & (var) $ \mathfrak {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathfrak {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathfrak {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] mathscr & {\color {red}$ \mathscr {\Gamma \Delta \Theta \Lambda \Xi \Pi \Sigma \Upsilon \Phi \Psi \Omega }$ } & (var) $ \mathscr {\varGamma \varDelta \varTheta \varLambda \varXi \varPi \varSigma \varUpsilon \varPhi \varPsi \varOmega }$ \\ & $ \mathscr {\alpha \beta \gamma \delta \epsilon \zeta \eta \theta \iota \kappa \lambda \mu \nu \xi \pi \rho \sigma \tau \upsilon \phi \chi \psi \omega }$ & (var) $ \mathscr {\varepsilon \vartheta \varpi \varrho \varsigma \varphi }$ \\ [6pt] \end {tabular}\end {document}
自定义命令 梳理一下各种自定义(重定义)命令的用法,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} \demo [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 }
对一个已经存在的命令用 \newcommand,或者对一个不存在的命令用 \renewcommand 都会导致编译报错,而且错误往往需要阅读报错输出才能查看。
除此之外,还有一个 \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 *{\max 2}{\mathop {\mathrm {max2}}}\[ \max 2_ 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 {\max 3}{max3}\DeclareMathOperator *{\max 3}{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 \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 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 \newcommand {\mat }[2]{{\mathbb {R}^ {#1 \times #2 }}}\newcommand {\trans }{\mathsf {T}}\newcommand {\hermite }{\mathsf {H}}\renewcommand {\le }{\leqslant }\renewcommand {\leq }{\leqslant }\renewcommand {\ge }{\geqslant }\renewcommand {\geq }{\geqslant }\renewcommand {\Re }{\operatorname {Re}}\renewcommand {\Im }{\operatorname {Im}}\renewcommand {\l }{\ell }\renewcommand {\k }{\kappa }\renewcommand {\d }{\, \mathrm {d}}\renewcommand {\i }{\mathrm {i}}\DeclareMathOperator {\rank }{rank}\DeclareMathOperator {\diag }{diag}\DeclareMathOperator {\range }{range}\DeclareMathOperator {\tr }{Tr}\DeclareMathOperator *{\argmax }{arg\, max}\DeclareMathOperator *{\argmin }{arg\, min}\DeclarePairedDelimiter {\inner }{\langle }{\rangle }\DeclarePairedDelimiter {\norm }{\lVert }{\rVert }
定理与证明环境 amsthm 宏包提供了定理类和证明类环境,但是它们并不是开箱即用的,这里记录一下相关的使用方式和配置。
在很多模板中经常会使用 tcolorbox 对定理环境进行美化,但是 tcolorbox 的使用非常复杂,光说明文档就好几百页,而且还可以结合 tikz 进一步自定义样式,这里暂时不讨论。
定理类环境 基于 amsthm 包可以创造定理类环境,语法包括如下几类
1 2 3 4 5 6 \newtheorem {name}{text} \newtheorem {name}{text}[section-level] \newtheorem {name}{text}[counter] \newtheorem {name}[counter]{text} \newtheorem *{name}{text}
其中
name:必选的定理类环境的标识符(名称)
text:必选的显示环境名称(引导词)
可选项的位置和名称有不同含义:
counter 在前面:共享前者的计数器,例如前者为1.1,后者则为1.2;
counter 在后面:继承前者的计数器,例如前者为1.1,后者则为1.1.1;
section-level 在后面:编号计数器依赖于某个章节层次,例如section 1的编号从1.1开始。
下面的常用环境都可以基于定理环境创建:(按照字体风格进行了分类)
plain 风格
定理 theorem
推论 corollary
引理 lemma
命题 proposition
definition 风格
定义 definition
例子 example
问题 problem
remark 风格
注记 remark(remark*)
笔记 note(note*)
使用时例如
1 2 3 \begin {theorem} ... \end {theorem}
或者可以加上额外名称,会在引导词后加上括号显示
1 2 3 \begin {theorem}[xxx] ... \end {theorem}
关于下面三个写法有必要辨析一下
1 2 3 \newtheorem {theorem}{Theorem}[section]\newtheorem {corollary}{Corollary}[theorem]\newtheorem {lemma}[theorem]{Lemma}
三者的区别为:
对于theorem,根据当前section创建子编号;
对于corollary,根据最近一次的theorem创建子编号,例如theorem 1.1之后的corollary采用编号1.1.1;
对于lemma,与theorem共享计数器,例如theorem 1.1之后的lemma则采用编号1.2。
可以使用 \theoremstyle{style} 命令修改定理环境的样式,内置样式有三种:
plain(默认样式):引导词是正体,内容是斜体,通常用于定理/推论/引理/命题等
definition:引导词和内容都是正体,通常用于定义/条件/示例/问题等
remark:引导词是斜体,内容是正体,通常用于remark/note/断言/结论等。不同于其他两个样式,它不会在环境的上下方添加额外间距,而且引导词不会加粗显示。
完整的定义语法如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 \theoremstyle {plain}\newtheorem {theorem}{Theorem}[section] \newtheorem {corollary}{Corollary}[theorem] \newtheorem {lemma}[theorem]{Lemma} \newtheorem {proposition}[theorem]{Proposition} \theoremstyle {definition}\newtheorem {definition}{Definition}[section] \newtheorem {example}{Example}[section] \newtheorem {problem}{Problem}[section] \theoremstyle {remark}\newtheorem {remark}{Remark}[section] \newtheorem *{remark*}{Remark} \newtheorem {note}{Note}[section] \newtheorem *{note*}{Note}
这里习惯使用 ABC* 表示与 ABC 相同语义,但是不带编号的环境。
我们还可以使用thmtools宏包更简单直观地实现上述定理的设置,与上面几乎等价的一组配置命令如下 (与上文不完全相等,这里进行了简化,直接将推论和命题等视作一类,共享定理的计数器)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \usepackage {thmtools}\declaretheorem [style=plain, numbered=yes, name=Theorem, numberwithin=section]{theorem}\declaretheorem [style=plain, name=Corollary, sibling=theorem]{corollary}\declaretheorem [style=plain, name=Lemma, sibling=theorem]{lemma}\declaretheorem [style=plain, name=Proposition, sibling=theorem]{proposition}\declaretheorem [style=definition, numbered=yes, name=Definition, numberwithin=section]{definition}\declaretheorem [style=definition, name=Example, numberwithin=section]{example}\declaretheorem [style=definition, name=Problem, numberwithin=section]{problem}\declaretheorem [style=remark, numbered=yes, name=Remark, numberwithin=section]{remark}\declaretheorem [style=remark, name=Remark, numbered=no]{remark*}\declaretheorem [style=remark, name=Note, numberwithin=section]{note}\declaretheorem [style=remark, name=Note, numbered=no]{note*}
补充:在定理类环境中如何直接使用列表环境,会导致第一项直接在首行的名称之后出现,与列表后续项的缩进不一致,看着很奇怪,可以通过在第一项之前加上\noindent实现。
证明类环境 amsthm也提供了用于写证明/解答的proof环境,不含有编号,默认样式包括:引导词Proof为斜体,内容是正体,结尾会自动添加证毕的方框符号。 可以直接使用,并不需要手动定义
1 2 3 \begin {proof} ... \end {proof}
在默认情况下,proof环境使用斜体的proof作为默认引导词。
通过修改\proofname可以替换默认引导词,例如可以将默认引导词改为加粗的正体 proof
1 \renewcommand *{\proofname }{\normalfont \bfseries Proof}
由于ctex默认会将\proofname修改为中文的证明,这里改回来
1 \renewcommand {\proofname }{\normalfont \bfseries Proof}
proof环境支持可选参数,可选参数会替换默认的引导词,例如
1 2 3 \begin {proof}[\normalfont \bfseries Solution] ... \end {proof}
可以用来强调是某个定理/命题的证明,尤其在定理和证明分离时,例如
1 2 3 \begin {proof}[\normalfont \bfseries Proof of Theorem~\ref {thm:1}] ... \end {proof}
可以简单地通过修改默认引导词定义一个与证明环境类似的解答环境。
1 \newenvironment {solution}{\begin {proof}[\textbf {Solution}]}{\end {proof}}
对于以不带编号公式结尾的证明,默认情况下证毕符号会另起一行,不太美观,可以使用\qedhere命令将证毕符号放在公式行的末尾,例如
1 2 3 4 5 6 \begin {proof} For simplicity, we use \[ E=mc^ 2 \qedhere \] \end {proof}
对于带编号的公式,则不建议使用\qedhere命令,因为编号和证毕符号的排版可能异常,不够美观。 对于多行公式最好也不要使用,因为证毕符号出现的位置可能不符合期望。
注:这里并没有对证明的引导词 Proof 采用缩进,可以加入\indent实现。
习题与解答环境 习题与解答环境也是一个常见的需求,下面提供一种直接基于 framed 宏包的简易实现,对于习题环境会加上背景色,习题环境不含编号。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 \documentclass {ctexart}\usepackage {xcolor,framed}\definecolor {shadecolor}{RGB}{241, 241, 255} \newenvironment {problem}{\begin {shaded}\noindent \textbf {题目: }}{\end {shaded}}\newenvironment {solution}{\par \noindent \textbf {解答: }}{\par }\begin {document}\begin {problem} 设 $ x^ 2 - 5x + 6 = 0$ ,求其根。 \end {problem}\begin {solution} 由因式分解得 $ x=2$ 或 $ x=3$ 。 \end {solution}\end {document}