Latex 语法简单总结

Hexo Next 开启 Mathjax

Hexo Next 主题默认支持 Mathjax 和 katex,以在博客文章中显示数学公式。其中,Mathjax 默认以『按需加载』的方式开着,只需要在 md 文件的头部区域添加 mathjax: true 即可激活该文的 Mathjax 支持。

1
2
3
4
5
---
layout: post
title: 'Latex 简单语法总结'
mathjax: true # 开启 Mathjax
---

也可以在 _config.next.yml 配置文件中设置 math: ↴ every_page: true 为所有文章开启数学公式支持。

Latex 语法

Mathjax 不只支持 Latex,还支持 MathML 等语法。本着快速入门的实用主义角度,本文只记录一部分 Latex 语法。

Latex 的基本语法包括:

  • 开头结尾与键盘字符。
  • 格式控制,包括公式组合、上下标、分数、根式、矩阵等 。
  • 转义字符,包括希腊字符、数学符号、运算符、箭头、修饰符等。
  • 打印控制,包括字体、颜色、大小、对齐等。
  • 宏定义与扩展包,包括自定义命令、环境等。

开头结尾与键盘字符

$ ... $ 包裹的内容会被 Mathjax 重新改写为 行内公式,比如 \$F=ma\$ 就会被自动渲染为 $F=ma$,行内公式后续文字会在同一行继续。用 $$ ... $$ 包裹的内容称为 行间公式 或者 块内公式,公式在文章中是独立的块,\$\$E=mc^2\$\$ 会被渲染为 $$E=mc^2$$ 文字将被断开换行并形成上下围绕。

对于英文字母以及一些键盘上的符号,Mathjax 也会适当地重新渲染,$+ - * / = > < ( ) [ ]$ 等均会被渲染为数学符号。因此像 F=ma 这样的公式,直接前后套上 $,变为 \$F=ma\$ 就是 Latex 表达式了。

格式控制:初步

从上面我们还注意到,c^2 经过 Mathjax 渲染后变成了 $c^2$。没错,^ 就是上标控制符,将紧随其后的字符变为上标。同理,_ 就是下标控制符。\$C_4^1 * C^2_4\$ 将渲染为 $C_4^1 * C^2_4$。上下标没有先后顺序,都会附着到前一个全高字符上。

当表达『24选4』时,\$C_24^4\$ 却被渲染为了 $C_24^4$。规则是严格执行的,但结果却不是我们想要的。这时候需要用到花括号 {} 来控制上下标的范围,用 \$C_{24}^4\$ 就能正确渲染为 $C_{24}^4$ 了。

{} 『分组符』不光能用于上下标,其用途如名字所言,是将若干 latex 表达式定义为一个组,以一个整体与表达式中其它部分作用。比如 \$1^{3^{5^{7^9}}}\$ $\Rightarrow$ $1^{3^{5^{7^9}}}$,就是先将 7^9 视为整体,作为 5 的上标,再以三者的组合作为整体,作为 3 的上标,以此类推直到完成这个叠幂公式。你甚至可以反过来,比如 \${{{1^3}^5}^7}^9\$ $\Rightarrow$ ${{{1^3}^5}^7}^9$。分组符的灵活应用是大型公式的基础之一。

注意看两种不同的叠幂公式的渲染效果,有什么不同?为什么?

$C_{24}^4$ 可以展开为 $(24 \cdot 23 \cdot 22 \cdot 21)/(1 \cdot 2 \cdot 3 \cdot 4)$。即通项公式 $C_n^k = \frac{1 \times 2 \times \dots \times k}{n (n-1) (n-2) (n-k+1)}$,其 Latex 表达式为 \$ C_n^k = \frac{1 \times 2 \times \dots \times k}{n (n-1) (n-2) (n-k+1)} \$

从这里我们开始入门大型公式。上述分数的表达式是 $\frac{分子}{分母}$,在 \frac 后面,分子和分母的位置是固定的,分子在前,分母在后,与上下标有所不同。大括号 {} 则继续发挥分组的作用。在分子分母两组内部,我们又用了 \times 作为乘号,\dots 作为三点省略号。Mathjax 会自动识别空格,因此我们不必担心空格的问题,在源代码上添加空格可以使阅读与编辑更方便,有时也能避免一些 latex 的编译错误。

在初步掌握格式控制后,就可以展开阅读以下表格了:

控制符 作用 效果 控制符 作用 效果
^ 上标 2^3 $\Rightarrow$ $2^3$ _ 下标 C_2 $\Rightarrow$ $ C_2$
{ } 分组 1^{3^5} $\Rightarrow$ $1^{3^5}$ \quad 宽度1em的空格$^*$ 1 \quad 2 $\Rightarrow$ $1\quad 2$
\frac 上下分式 \frac 1 2 $\Rightarrow$ $\frac 1 2$ \over 上下分式 1 \over 2 $\Rightarrow$ $ {1\over2}$
\sqrt 根号 \sqrt[3]{27} $\Rightarrow$ $\sqrt[3]{27}$ \binom 组合数 \binom{4}{24} $\Rightarrow$ $\binom{4}{24}$
\left( 左大括号$^*$ \left( \frac{4}{24} \right) $\Rightarrow$ $\left( \dfrac4{24} \right)$ $\Leftrightarrow$ \right) 右大括号 <反例> (\frac{4}{24}) $\Rightarrow$ $( \dfrac4{24} )$
\left[ 左大方括号 \left[ \frac{4}{24} \right] $\Rightarrow$ $\left[ \dfrac4{24} \right]$ $\Leftrightarrow$ \right] 右大方括号 <反例> [\frac{4}{24}] $\Rightarrow$ $[ \dfrac4{24} ]$
\left\{ 左大方括号 \left\{ \frac{4}{24} \right\} $\Rightarrow$ $\left\{\dfrac4{24}\right\}$ $\Leftrightarrow$ \right] 右大方括号 <反例> \{\frac{4}{24}\} $\Rightarrow$ $\{\dfrac4{24}\}$

* 为兼容源代码的可读性,Latex 会忽略普通空格。因此在公式中需要添加额外空格时要用 \quad。后续排版环节会介绍更多距离控制符。
* 在所属代码块内,以最大上下范围为准,自动调整括号大小。

转义字符与修饰符号

在数学中我们会用到很多字符,比如圆周率 π,积分符号 ∫,无穷大 ∞,等等。归功于 unicode 的普及,我们可以直接从输入法的特殊字符输入,或者其它查码表的方式来输入这些字符,Mathjax 也都是支持的。但 Latex 出身甚早,自身也提供了一套转义字符以输入这些特殊字符,显示效果也更好。

希腊字符

小写希腊字符 Latex 转义 Mathjax 效果 大写希腊字符 Latex 转义 Mathjax 效果 Unicode
α \alpha $\alpha$ Α \Alpha $\Alpha$ x0391
β \beta $\beta$ Β \Beta $\Beta$ x0392
γ \gamma $\gamma$ Γ \Gamma $\Gamma$ x0393
δ \delta $\delta$ Δ \Delta $\Delta$ x0394
ϵ \epsilon $\epsilon$ Ε \Epsilon $\Epsilon$ x0395
ζ \zeta $\zeta$ Ζ \Zeta $\Zeta$ x0396
η \eta $\eta$ Η \Eta $\Eta$ x0397
θ \theta $\theta$ Θ \Theta $\Theta$ x0398
ι \iota $\iota$ Ι \Iota $\Iota$ x0399
κ \kappa $\kappa$ Κ \Kappa $\Kappa$ x039a
λ \lambda $\lambda$ Λ \Lambda $\Lambda$ x039b
μ \mu $\mu$ Μ \Mu $\Mu$ x039c
ν \nu $\nu$ Ν \Nu $\Nu$ x039d
ξ \xi $\xi$ Ξ \Xi $\Xi$ x039e
ο \omicron $\omicron$ Ο \Omicron $\Omicron$ x039f
π \pi $\pi$ Π \Pi $\Pi$ x03a0
ρ \rho $\rho$ Ρ \Rho $\Rho$ x03a1
σ \sigma $\sigma$ Σ \Sigma $\Sigma$ x03a3
τ \tau $\tau$ Τ \Tau $\Tau$ x03a4
υ \upsilon $\upsilon$ Υ \Upsilon $\Upsilon$ x03a5
ϕ \phi $\phi$ Φ \Phi $\Phi$ x03a6
χ \chi $\chi$ Χ \Chi $\Chi$ x03a7
ψ \psi $\psi$ Ψ \Psi $\Psi$ x03a8
ω \omega $\omega$ Ω \Omega $\Omega$ x03a9
可以看到,希腊字母的转义就是它的英语名称前加反斜杠 `\`。大写希腊字母则首字母大写。同时也会注意到,不少大写的 Mathjax 渲染效果并不是西腊字符,而是将源码染红了。

标红是因为 Mathjax 认为它是错误代码。标红错误代码有助于作者顺利进行排查,比如 $\fracc{k}{n(n-k)}$ 很容易便能看出来是 \frac 拼写错误。但为何 $\Alpha$ 是错误的呢?原因如下:

[引用] There is no uppercase Alpha, Beta etc. defined in LATEX2ε because it looks the same as a normal roman A, B.

由于历史原因,Latex 以『形状相似』为由,没有定义几个与英文相似的大写希腊字母,包括 Α Β Ε Ζ Τ 等,遇到就报错,建议你用英文字母代替这几个大写希腊字符。所以 Mathjax 也跟着报错了。仔细想来,只是用于公式排版倒也差不多说得过去。只是极端节省到这地步,我的心情如下述评论:

[引用] The fact that they actually bothered to make a capital tau symbol surprises me ...

这种情况下,如果有必要输入正确的大写希腊字符,例如某些可能会被复制的场合。可以直接用输入法的特殊字符输入,或者用 Latex 后续版本扩展出来的 \unicode{} 方法,例如 \$\unicode{x0391} \neq \text{A}\$ $\Rightarrow$ $\unicode{x0391}\neq \text{A}$。

数学符号

Latex 定义了大量的符号,下表只列出了一小部分。大部分符号用不到就是不需要,知识领域没覆盖那部分。这里 有一份号称完整的符号表,不过比起查书,问问 ChatGPT 也许更直接。

效果 Latex 效果 Latex 效果 Latex 效果 Latex
$\infty$ \infty $\aleph$ \aleph $\because$ \because $\therefore$ \therefore
$\approx$ \approx $\neq$ \neq $\equiv$ \equiv $\mid$ \mid
$\oplus$ \oplus $\pm$ \pm $\parallel$ \parallel $\nparallel$ \nparallel
$\times$ \times $\div$ \div $\forall$ \forall $\exists$ \exists
$\cup$ \cup $\cap$ \cap $\subset$ \subset $\supset$ \supset
$\in$ \in $\notin$ \notin $\sum$ \sum $\prod$ \prod
$\partial$ \partial $\int$ \int $\iint$ \iint $\oint$ \oint
$\geq$ \geq $\leq$ \leq $\gg$ \gg $\ll$ \ll
$\to$ \to $\gets$ \gets $\mapsto$ \mapsto $\leadsto$ \leadsto
$\uparrow$ \uparrow $\upuparrows$ \upuparrows $\Uparrow$ \Uparrow $\downarrow$ \downarrow
$\updownarrow$ \updownarrow $\leftrightarrow$ \leftrightarrow $\twoheadrightarrow$ \twoheadrightarrow $\xtwoheadrightarrow{abc}$ \xtwoheadrightarrow{abc}
$\curvearrowleft$ \curvearrowleft $\curvearrowright$ \curvearrowright $\circlearrowleft$ \circlearrowleft $\circlearrowright$ \circlearrowright
$\square$ \square $\triangle$ \triangle $\perp$ \perp $\angle$ \angle
$\lim$ \lim $\log$ \log $\sin$ \sin $\cos$ \cos

特殊转义符

我们使用 $ ... $$$ ... $$ 来包裹 Latex 表达式,用 {} 来分组包裹,用 ^_ 作为上下标。那么当我们需要在公式中直接显示这几个字符时,就需要额外添加转义符了。

转义字符 Latex 表示法 Mathjax 效果 说明
$ _ { } \\$ \_ \{ \} \\{ \\_ \\\$ \\} $\Rightarrow$ $ \{ \_ \$ \}$ 普通地添加 \ 前缀即可,{} 大括号本身也是公式常用字符。
^ \verb!^! $^*$ 3\verb!^!3=27 $\Rightarrow$ $3\verb!^!3=27$ \verb 可能在一些复杂公式中与其它控制符冲突。
^ ^\wedge 3^\wedge3=27 $\Rightarrow$ $3^\wedge3=27$ 只是像,不是同一个字符。但参考上文,像有时就够了。
\ \backslash C:{\backslash}Windows $\Rightarrow$ $ C:{\backslash}Windows$ 这里用到 { } 是因为要与 Windows 这个单词分开。

* verb 是 verbatim 的简写,verbatim text 意为原始文本。\verb 的语法较为特殊,首先以 \verb 开头,然后紧接着一个界定符,这个界定符可以是 ! | # 等各种符号任选,只需要与正文不冲突即可,再继续输入正文,最后再以相同的界定符结尾。两个界定符之间的内容将被原样输出,不会被 Mathjax 渲染。界定符甚至可以是数字,比如 \$\verb03^30\$ 将输出 $\verb03^30$,前后两个 0 成为了首尾界定符,但唯独不能是字母,因为会和 verb 本身形成新的单词短语导致解析错误,\$\verba3^3a\$ $\Rightarrow$ $\verba3^3a$。

修饰符号

效果 Latex 效果 Latex 效果 Latex 效果 Latex
$\hat{abc}$ \hat{abc} $\widehat{abc}$ \widehat{abc} $\bar{abc}$ \bar{abc} $\overline{abc}$ \overline{abc}
$\vec{abc}$ \vec{abc} $\overrightarrow{abc}$ \overrightarrow{abc} $\dot{abc}$ \dot{abc} $\ddot{abc}$ \ddot{abc}
$\tilde{abc}$ \tilde{abc} $\widetilde{abc}$ \widetilde{abc} $\overbrace{abc}^n$ \overbrace{abc}^n $\underbrace{abc}_n$ \underbrace{abc}_n

修饰符号的使用类似于函数,用 {} 将修饰对象包裹起来,修饰符号的位置总是相对于修饰对象进行调整,而与修饰对象在整个公式中的位置无关。

从大型运算符到修饰命令

我们在前面已经见到了 \sum \prod \int 等大型运算符,这些符号在公式中往往还配有上下限、积分定义域等算子与脚标。Mathjax 会自动根据行内或块内的场景来调整算子的大小和脚标的相对位置。比如 \$\sum_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6\$ 将渲染为 $\sum_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6$,而相同的公式在块内渲染为:

$$\sum_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6$$

可以看到,$_{i=1}$ 与 $^n$ 的位置随着不同的条件自动调整了。这种自动调整的机制在大型公式中非常有用,我们只需要关心公式的结构即可。但如果一定要坚持特定的格式,也可以用 \limits 和 \nolimits 来强制调整上下限的位置。比如 \$\sum\limits_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6\$ 将渲染为 $\sum\limits_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6$。而\$\$\sum\nolimits_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6\$\$ 将渲染为:

$$\sum\nolimits_{i=1}^n i^2 = \frac {n(n+1)(2n+1)} 6$$

\limits\nolimits 没有自己的符号,但可以修饰很多带脚标的大形运算符,强制调整其形式,且只能用在运算符上。如果你用在别处,Mathjax 会报错。比如: \$C\limits_4^2\$ $\Rightarrow$ $C\limits_4^2$,报错了。我们期望的是 4 出现在 C 的下方,正确的实现方式是用下面的 \underset 命令:

修饰命令
作用
效果
\limits \nolimits 强制上下限以指定场景显示 上文已述
\substack{} 创建一个多行块,整体通常作为上下标 \sum_{\substack{0<i<3\\\\0<j<5}}a_{ij} $\Rightarrow$ $\sum_{\substack{0<i<3\\0<j<5}}a_{ij}$
\mathop{} 将 { }内的内容整体视作一个大型运算符 \mathop{\sum\sum}\limits_{i \neq j} (i *j) $\Rightarrow$ $\mathop{\sum\sum}\limits_{i \neq j} (i *j)$
\mbox{} { } 内的文本不会断行,可能导致溢出 \mbox{ ... very long contnet ... } $\Rightarrow$ $$\mbox{Very very very very very very very long content in the mbox and there is no line break. }$$
\sideset{}{}\prod 在 \prod 的左右边分别添加指定内容 \sideset{_1^2}{_3^4}\prod $\Rightarrow$ $\sideset{_1^2}{_3^4}\prod$
\overset{A}{B} 在内容 B 的上方添加内容 A 2Cu+2Al\overset{\triangle}{=}2Au+Cl_2\uparrow $\Rightarrow$ $2Cu+2Al\overset{\triangle}{=}2Au+Cl_2\uparrow$
\underset{A}{B} 在内容 B 的下方添加内容 A \underset{probability}{P}(X=x) = \frac{1}{x}^2 $\Rightarrow$ $\underset{probability}{P}(X=x) = \frac{1}{x}^2$

多行公式组:矩阵,表格及其它

equation 与 cases

经过前面的铺垫,我们可以开始对公式进行组合了。公式组的基本形式是:

1
2
3
4
5
6
\begin{equation}
\begin{cases}
x + y = 35 \\
2x + 4y = 94
\end{cases}
\end{equation}

效果如下:
\begin{equation}
\begin{cases}
x + y = 35 \\
2x + 4y = 94
\end{cases}
\end{equation}

  • 多行公式组不需要以 $ ... $ 包裹,但需要以 \begin{env} \end{env} 单独的首尾声明作为公式起止。env 则是由 latex 预先定义的一些环境,比如上面的 equation 就是一个环境。
  • equation 环境的作用是将包裹的所有内容视作一个公式全局自动编号,编号的位置在公式组的最右侧。而 cases 环境的作用是为包裹的所有内容添加左大括号,形成一个公式组。
  • 公式组内部仍可以用其它的公式控制符,比如 \frac \sum \int 等。
  • 公式组内部通常都有多行,需要用 \\ 来换行。Latex 源码的回车换行和空格一样会在渲染时忽略,多行 latext 公式组在源码上仍然可以只写成一行,\\begin{equation}\\begin{cases}x+y=35\\\\2x+4y=94\end{cases}\end{equation} 的效果是一样的,但合理书写可以让源码可读性及可编辑性更高。
  • \begin{env} \end{env} 是可以嵌套的,在上面的例子中,我们用了两个环境,在 equation 环境内部嵌套了 cases 环境,效果是将鸡兔同笼的两个二元一次方程合并成组,并做了全局编号。

align 与 align*

align 的作用是将每一个包裹的公式对齐,比较适合于表现演算过程。要注意的是,align 并不会自动以 $=$ 对齐,而是要用 & 指定竖向对齐位置。比如:

1
2
3
4
5
6
\begin{align}
f(x) &= x^4 + 4 \\
&= x^4 + 4x^2 + 4 - 4x^2 \\
&= (x^2 + 2)^2 - (2x)^2 \\
&= (x^2 + 2x + 2)(x^2 - 2x + 2)
\end{align}

得到:
\begin{align}
f(x) &= x^4 + 4 \\
&= x^4 + 4x^2 + 4 - 4x^2 \\
&= (x^2 + 2)^2 - (2x)^2 \\
&= (x^2 + 2x + 2)(x^2 - 2x + 2)
\end{align}

可以看到,每个公式后面都加上了全局编号,如果不想要的话,可以用 align* 来代替 align,效果如下:

\begin{align*}
f(x) &= x^4 + 4 \\
&= x^4 + 4x^2 + 4 - 4x^2 \\
&= (x^2 + 2)^2 - (2x)^2 \\
&= (x^2 + 2x + 2)(x^2 - 2x + 2)
\end{align*}

同样的情况也适用于 equation,即无编号公式 equation*,不再演示。

matrix 矩阵与省略号

matrix 环境用于矩阵排版,例如:

1
2
3
4
5
\begin{matrix}
a_1 & b_1 & c_1 \\
a_2 & b_2 & c_2 \\
a_3 & b_3 & c_3
\end{matrix}

\begin{matrix}
a_1 & b_1 & c_1 \\
a_2 & b_2 & c_2 \\
a_3 & b_3 & c_3
\end{matrix}
同样是用 & 来进行上下对齐。上述渲染结果相比于常见的矩阵缺少了左右 $[ ]$,可以使用上文的 \left[ \right] 命令来添加:

1
2
3
4
5
6
7
$$\left[    
\begin{matrix}
a_1 & b_1 & c_1 \\
a_2 & b_2 & c_2 \\
a_3 & b_3 & c_3
\end{matrix}
\right]$$ % 当内容放在 \begin \end 之外时,需要用 $ 或 $$ 包裹

$$\left[
\begin{matrix}
a_1 & b_1 & c_1 \\
a_2 & b_2 & c_2 \\
a_3 & b_3 & c_3
\end{matrix}
\right]$$

也可以用 pmatrix bmatrix Bmatrix vmatrix Vmatrix 等环境来代替 matrix,效果如下:
$$ \text{pmatrix:}\begin{pmatrix} a_1 & b_1 \\ a_2 & b_2 \end{pmatrix}, \text{bmatrix:}\begin{bmatrix} a_1 & b_1 \\ a_2 & b_2 \end{bmatrix}, \text{Bmatrix:}\begin{Bmatrix} a_1 & b_1 \\ a_2 & b_2 \end{Bmatrix},\text{vmatrix:}\begin{vmatrix} a_1 & b_1 \\ a_2 & b_2 \end{vmatrix}, \text{Vmatrix:}\begin{Vmatrix} a_1 & b_1 \\ a_2 & b_2 \end{Vmatrix}$$

另外还有一个 smallmatrix 环境,用于在行内排版小矩阵,如下: \$\left(\\begin{smallmatrix}a_1&b_1\\\\a_2&b_2\end{smallmatrix}\right)\$ $\Rightarrow$ $\left(\begin{smallmatrix} a_1 & b_1 \\ a_2 & b_2 \end{smallmatrix}\right)$,但它没有 \smallBmatrix 等变化形式,需要括号时用普通的即可。

当矩阵很大时,会使用省略号来代替部分内容:

1
2
3
4
5
6
\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}

\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}

我们上文用过 \dots,此处又使用了 \cdots \vdots \ddots 等命令来输出省略号,可以认为前缀字母 c = center,v = vertical,d = diagonal,分别表示水平、垂直、对角线方向。另外还有 \ldots,l = lower 表示靠近底线的省略号。因此也可以把前缀字母理解为类似于 \limits 的某种修饰符。

array

array 可以起到与 matrix 一致的效果,但可以容纳更多的修饰或控制符使得表现效果更丰富,当然也意味着更多的 latex 代码量和复杂度。因为可以添加横竖线作为表格边框,array 一般用来表现表格:

1
2
3
4
5
6
7
\begin{array}{c|lcr} 
n & 左对齐 & 居中对齐 & 右对齐 \\
\hline % 横线不占用行高,不必添加 \\ 换行
1 & \pi & rad & 355/113 \\
2 & e & {\left(1+\frac{1}{n}\right)}^n & \ln x \\
3 & i & \sqrt{-1} & sin(\theta)+icos(\theta)
\end{array}

效果:
$$\begin{array}{c|lcr}
n & 左对齐 & 居中对齐 & 右对齐 \\
\hline
1 & \pi & rad & 355/113 \\
2 & e & {\left(1+\frac{1}{n}\right)}^n & \ln x \\
3 & i & \sqrt{-1} & sin(\theta)+icos(\theta)
\end{array}$$

代码首行 \begin{array}{c|lcr} 中的 {c|lcr} 部分是 array 环境的参数,用于指定每一列的对齐方式,c = center,l = left,r = right,| 表示添加竖线作为列分隔符,可以不添加也可以添加多条。在内容部分,用 & 来对齐各列,用 \\ 来换行。用 \hline 添加横线,会自动置入两行之间,不影响文本的行高,也不必添加 \ 换行。

{array}也同样可以配合 \left{ \right} 来构造方程组,一些形式上要求齐次对齐的方程组,使用 array 会比较方便:

1
2
3
4
5
6
7
8
$$\left\\{ 
\begin{array}{lrrrrr}
f_1(x) = & & & & x & +1 \\
f_2(x) = & & & 8x^2 & +5x & +2 \\
f_3(x) = & & 3x^3 & +7x^2 & +2x & +9 \\
f_4(x) = & 9x^4 & +3x^3 & & +4x & +6
\end{array}
\right.$$ % 有 \left\{ 时,必须要有对应的右括号闭合。但可以用 \right. 放一个不显示内容的右括号。

$$\left\{
\begin{array}{lrrrrr}
f_1(x) = & & & & x & +1 \\
f_2(x) = & & & 8x^2 & +5x & +2 \\
f_3(x) = & & 3x^3 & +7x^2 & +2x & +9 \\
f_4(x) = & 9x^4 & +3x^3 & & +4x & +6
\end{array}
\right.$$

公式引用

\tag \label 与 \eqref

公式引用分为被引用,和引用别人的。虽然使用 \begin{equation} 等环境可以自动编号,但却无法直接根据该编号引用对应的公式。在 Latex 中引用公式,必须满足两个条件:

  1. 被引用的公式必须是块公式,行内公式不能被引用。
  2. 被引用的公式必须显式地声明一个 label,用于引用的锚点,语法为 \label{labelname}。

公式也可以用 \tag{equationname} 来修改默认的全局编号名,但并非必须。

1
2
3
4
5
\begin{equation}
\label{ef}
\tag{Euler's Formula} % 自定义公式名,非必须
e^{i\pi} + 1 = 0
\end{equation}

\begin{equation}
\label{ef}
\tag{Euler's Formula}
e^{i\pi} + 1 = 0
\end{equation}

在上面的例子中,我们为欧拉公式添加了一个 label ef。如果我们想要引用这个公式,可以使用 \eqref{ef} 命令,引用时则不限于是否是块公式,也不限于是否有 \tag{tagname},例如:

\$e^{i\theta}\overset{\\eqref{ef}}{=}cos\theta+isin\theta\$ $\Rightarrow$ $e^{i\theta}\overset{\eqref{ef}}{=}cos\theta+isin\theta$。

可以看到,引用的锚点是 \label{labelname} $\Rightarrow$ \\eqref{ labelname},而在 \eqref 处显示的则是由 \tag{equationname} 设定的公式名称。labelname 可以是几乎任意字符串,在各种教程中经常出现的 \label{eq:1} 主要是为了方便管理,取『equation No.1』之意。上面的 ef 也是 Euler's Formula 的缩写。使用 \label 的好处在于,当我们在后续编辑排版时,即使公式的编号变了,引用的地方也会自动更新,因为引用的锚点是固定的。这也是为什么要分别定义 \label 和 \tag 的原因。

\ref 与 \href

在完整的 latex 中,\ref 与 \eqref 稍有不同,后者是前者子集。但对于 Mathjax 这种限于网页展示的场合,两者并没有什么不同。根据 这里 的说明,\ref 还能引用外链,但我没有尝试成功,可能是 Mathjax 的限制。本来,在 Markdown 博客中引用外链有更简单的方式:[文字](链接地址),但如果非得拧巴一下,也可以用 \href{链接地址}{文字} 来实现:

$\href{https://www.kaikai.men/mathjax-latex-syntax/}{本文地址}$ $\Rightarrow$ $\href{https://www.kaikai.men/mathjax-latex-syntax/}{本文地址}$

打印控制

Latex 会自动调整公式的大小和排版,但有时候我们也需要适当地调整一下字体字号、空隙间距等,以达到更好的排版效果。这里介绍一些常用的控制命令。

空格间距

Latex 源码
效果
说明
ab $ab$ ab 间无空格
a b $a b$ a b 间有空格,无效
a\ b $a\ b$ 使用 \ 转义的空格,有效
a\  b $a\ b$ 第二空格未转义,无效
a\ \ b $a\ \ b$ 两个\ 转义的空格,有效
a\quad b $a\quad b$ quad 为 1em,一般相当于三个空格
a\qquad b $a\qquad b$ qquad 为 2em
a\,b $a\,b$ 半个空格
a\:b $a\:b$ 2/3 个空格
a\;b $a\;b$ 5/6 个空格
a\!b $a\!b$ 负向半个空格,常用于绘制长等号,如: =\!=\!= $\Rightarrow$ $=\!=\!=$

行间距

公式组的多行之间通过 \\\\ 分隔,在分隔符后面可以添加下方行距,允许小数点,如下:

1
2
3
4
5
\begin{cases}
x + y = 35 \\[15pt]
2x + 4y = 94 \\[1.5em]
x = 23, y = 12
\end{cases}

\begin{cases}
x + y = 35 \\[15pt]
2x + 4y = 94 \\[1.5em]
x = 23, y = 12
\end{cases}

字形字号

字形 Latex 效果 字体 Latex 效果 字体 Latex 效果
Roman 正体 \rm E $\rm E$ Italic 斜体 \it E $\it E$ Bold 黑体 \bf E $\bf E$
Calligraphic 草书 \cal E $\cal E$ Fraktur 尖角体 \frak E $\frak E$ Blackboard Bold 黑板粗体 \Bbb E $\Bbb E$
Sans-serif 无衬线体 \sf E $\sf E$ Typewriter 等宽 \tt E $\tt E$ Script 花体 \scr E $\scr E$
字号 Latex 效果 字号 Latex 效果 字号 Latex 效果
tiny \tiny E $\tiny E$ scriptsize \scriptsize E $\scriptsize E$ small \small E $\small E$
normalsize \normalsize E $\normalsize E$ large \large E $\large E$ Large \Large E $\Large E$
LARGE \LARGE E $\LARGE E$ huge \huge E $\huge E$ Huge \Huge E $\Huge E$

字体颜色

Mathjax 使用 \color{colorname} 命令来设置字体颜色,colorname 可以是预定义的颜色名,也可以是 RGB 值。比如 \$\color{red} E\$ $\Rightarrow$ $\color{red} E$。预定义的颜色名参考 这里,摘抄一部分如下:

$\color{aqua}{aqua}$ $\color{black}{black}$ $\color{blue}{blue}$ $\color{blueviolet}{blueviolet}$ $\color{brown}{brown}$ $\color{burlywood}{burlywood}$ $\color{cadetblue}{cadetblue}$ $\color{chocolate}{chocolate}$ $\color{coral}{coral}$ $\color{cornflowerblue}{cornflowerblue}$ $\color{crimson}{crimson}$ $\color{cyan}{cyan}$ $\color{darkblue}{darkblue}$ $\color{darkcyan}{darkcyan}$ $\color{darkgoldenrod}{darkgoldenrod}$ $\color{darkgray}{darkgray}$ $\color{darkgreen}{darkgreen}$ $\color{darkkhaki}{darkkhaki}$ $\color{deeppink}{deeppink}$ $\color{deepskyblue}{deepskyblue}$ $\color{dimgrey}{dimgrey}$ $\color{firebrick}{firebrick}$ $\color{forestgreen}{forestgreen}$ $\color{fuchsia}{fuchsia}$ $\color{gainsboro}{gainsboro}$ $\color{gold}{gold}$ $\color{goldenrod}{goldenrod}$ $\color{gray}{gray}$ $\color{green}{green}$ $\color{greenyellow}{greenyellow}$ $\color{grey}{grey}$ $\color{hotpink}{hotpink}$ $\color{indianred}{indianred}$ $\color{indigo}{indigo}$ $\color{lightblue}{lightblue}$ $\color{lightcoral}{lightcoral}$ $\color{lightsalmon}{lightsalmon}$ $\color{lightseagreen}{lightseagreen}$ $\color{lightskyblue}{lightskyblue}$ $\color{lime}{lime}$ $\color{limegreen}{limegreen}$ $\color{magenta}{magenta}$ $\color{maroon}{maroon}$ $\color{navy}{navy}$ $\color{olive}{olive}$ $\color{orange}{orange}$ $\color{orangered}{orangered}$ $\color{orchid}{orchid}$ $\color{peru}{peru}$ $\color{pink}{pink}$ $\color{plum}{plum}$ $\color{purple}{purple}$ $\color{red}{red}$ $\color{salmon}{salmon}$ $\color{silver}{silver}$ $\color{teal}{teal}$ $\color{thistle}{thistle}$ $\color{tomato}{tomato}$ $\color{turquoise}{turquoise}$ $\color{violet}{violet}$ $\color{yellow}{yellow}$ $\color{yellowgreen}{yellowgreen}$

如果使用 RGB,格式为 \color{#rrggbb} 或缩写的 \color{#rgb},其中 rgb 为 0-f 的十六进制数。

这里有一个新的注意点,在下一节中介绍。

宏定义与扩展包

Mathjax 不支持这些。Latex 本身提供了很多扩展功能,但 Mathjax 仅仅是一个 JS 库,它并不是完整的 Latex。如果需要使用这些功能,需要在 Latex 编译器中进行。

在这里记一笔,是因为在搜索某个效果的 Latex 语法时,往往会遇到一些使用扩展功能的回答,Mathjax 其实并不支持,需要注意。

与 Markdown 和 Hexo 的冲突处理

这个博客是 Hexo 搭建,加载了 Hexo Next 主题。使用 Markdown 语法在文本文件中编写博客,由 Hexo 将其编译为 HTML 文件,而 Mathjax 则在 HTML 文件中渲染 Latex 公式。而 Hexo 本身也有自己的模板语法,这使得我们编写的内容,需要经过 Hexo 编译,Markdown 编译,再由 Mathjax 渲染,最后才能在浏览器中显示。这样的多重编译过程,使得我们在写文章时,需要额外考虑一些情况。

Hexo 处理

使用 {% raw %} ... {% endraw %} 避免 Hexo 模板语法带来的问题。所有 {% raw %} ... {% endraw %} 两者之间的内容都不会被 Hexo 进一步解释,而是进入 Markdown 解释器层进行下一步处理。

在使用 \color{#rrggbb} 语法时就会遇到相关问题,{# 会被 Hexo 识别,但又不属于合法的模板语法,导致 Hexo 编译失败报错。相似的情况还出现在 {} 的嵌套场景下,连续的 {{{ 也会被视为错误的 Hexo 模板语法。因此,我们需要用 {% raw %} ... {% endraw %} 来避免这些问题。

Markdown 处理

Markdown 语法中,\ 也是转义字符,用于输出特殊字符,比如 \# $\Rightarrow$ # ,\* $\Rightarrow$ * 等。因为 #、*、_ 等字符在 Markdown 中是有意义的(用于标题、列表、强调等),因此需要用 \ 转义。所以为了在 Markdown 处理完以后还能保留 \,我们在写文章时就需要有意地写成 \\\\。

此外,Markdown 本身也会有意地忽略多余的空格,因此如果需要将多个空格传递给 html,需要使用 &nbsp; 来转义。所幸 &nbsp; 只要隔开连续的空格,每个空格包括 &nbsp; 都会保留,因此可以与空格交替写来省点事。

Mathjax 处理

在经过 Markdown 编译后,原始文章已经变成了 HTML 文件。此时 Mathjax 会搜索全文中的 Latex 相关语法,将其渲染为对应的公式。但是由于 Mathjax 也将 \$ 等符号视作特殊字符,因此仍然会再进行一次转义。比如 HTML 中如果有一个『\\\$』,会被 Mathjax 认为是 \$ 符号的转义符,因此会消除 \\,单显示一个 $ 符号。

与此相似的,还有为了在 Mathjax 渲染后还能正常显示 \\\\ (两个反斜杠),我们在源文件中需要写成惊人的八条反斜杠:\\\\\\\\\\\\\\\\。在 Markdown 编译时,每两条 \\ 会被解释为一条有效的反斜杠,因此在 HTML 文件中会生成连续的四条反斜杠。而 Mathjax 会在 HTML 呈现的内容基础上再作渲染,再一次将每两条反斜杠编译为一条有效的反斜杠,因此最终显示的是两条反斜杠。

如果能及时注意到 Mathjax 是在页面的 HTML 上再次渲染,就能很好地理解这个过程。

其它信息

本文到这里就差不多尾声了。Mathjax 是为网页提供 latex 公式渲染的 JS 库,并不拥有 latex 的全部功能。Latex 有很多全页排版、宏定义与扩展包,包括自定义命令、环境等功能,在 Mathjax 里是没有的。

本文的目的是为了介绍 Mathjax 的基本语法,以及与 Markdown 和 Hexo 的冲突处理。如果需要更多的功能,可以参考下面的参考资料。

Mathjax 的官方文档:https://docs.mathjax.org/en/latest/index.html

Mathjax 的官方示例:https://docs.mathjax.org/en/latest/web/start.html#mathjax-cdn

Latex 编辑器:TEXMaker

MathJax basic tutorial and quick reference

LaTeX Grammar List @rollpie