2.11. 数学公式

Note

reStructuredText 中支持的数学公式使用 LaTeX 语法。对使用 LaTeX 书写数学公式不熟悉的读者,可以在网络上找到许多入门语法;或者,也可以参考我撰写的 《简单粗暴LaTeX》一书 中的数学公式章节。

行内数学公式直接使用角色 :math: ,例如 \(sin\alpha\) ,这里主要讲行间公式的处理。

reStructuredText 语法中使用 math 指令( Directive: math )来插入行间数学公式。

数学公式语法上与 LaTeX 的原生命令一致。

单行公式可以直接写在指令的同一行,比如 ..math:: a + b = c 。

(2.11.1)\[a + b = c\]

多行公式需要在公式间插入一个空白行。

数学公式中可以使用与符号 & 来对齐列,使用双反斜线 \\ 来换行。Sphinx 会自动将整个块放在一个 LaTeX 语法的 split 环境中。

关于 Sphinx 中的数学公式使用:

Note

在 Sphinx 输出 HTML 时,建议在 conf.py 中加载 sphinx.ext.mathjax 插件。本文档开启了该插件,且**配置了 MathJax 的自动编号**。下文中所有右侧的编号都由 MathJax 提供,而左侧的、位于公式前一行的编号是 Sphinx 构建的结果。当然,这两者的格式都可以在配置(或 CSS 文件)中进行变更。

Sphinx 用户可以参考下文的 MathJax 支持 一节来获取更多关于 MathJax 的信息。

Sphinx 支持以 :label:TEXT 选项来给公式添加编号,并使其能够被 :eq: 角色交叉引用。更复杂的引用可以使用 MathJax 中的功能支持,见 MathJax 支持 一节。

Sphinx 支持以 :nowrap: 选项来取消自动公式环境(equation, align, split),而显式地由读者自行指定。

示例

单行公式的例子如下。使用 Eq.2.11.2 引用时会显示 (1) 这个链接。

(2.11.2)\[\int_1^\infty \frac{1}{x^2} dx = 1\]

使用 & 与 \ 进行标记的对齐多行公式,引用如 (2) 。

(2.11.3)\[\begin{split}(a + b)^2 &= (a + b)(a + b) \\ &= a^2 + 2ab + b^2\end{split}\]

用空白行分隔的多个公式,在 MathJax 支持下的 HTML 输出会默认向右对齐。如果开启了 MathJax 的自动编号,那么右侧会对整体附加一个序号(而不是给每行编号);这类似于 LaTeX 中的 split 环境。

(2.11.4)\[ \begin{align}\begin{aligned}f(x) = x^2 + \sin x\\S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \}\end{aligned}\end{align} \]

如果要居中对齐,使用 :nowrap: 选项配合 LaTeX 语法中的 gather(*) 环境:

无编号多行居中:

.. math::
    :nowrap:

    \begin{gather*}
    f(x) = x^2 + \sin x \\
    S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \}
    \end{gather*}
无编号多行居中:

要给多行公式中的每一行进行自动编号(并使它们在文中能够被交叉引用),参考 多行公式引用 一节。

MathJax 支持 MathJax ( 官方文档 )是一个 JavaScript 数学公式渲染引擎。在使用 Sphinx 将 reStructuredText 文档转换为 HTML 后,往往需要用 MathJax 来支持其中的数学公式输出。

Sphinx 中启用 MathJax 的方式是在 conf.py 中加载 sphinx.ext.mathjax 插件:

# 向 extensions 变量中添加一项 ‘sphinx.ext.mathjax’ extensions = [‘sphinx.ext.mathjax’, …] 在 conf.py 中,我们还可能需要配置 mathjax_config 变量来设置 MathJax,比如启用 MathJax 支持的 公式自动编号 :

警告

由于 reStructuredText 与 MathJax 语法的兼容性,Sphinx 并非接受 MathJax 的所有功能。MathJax 的自动编号在 Sphinx 文档中很难进行交叉引用,因此仍然推荐使用 Sphinx 的 :label: 角色。

同理,在 reStructuredText 文档中,应当使用 :math: 行内角色,而不是 MathJax 支持的 $..$ 语法。

# 如果是 MathJax v2,使用:
# mathjax2_config = {
#    'TeX': {
#        'equationNumbers': { 'autoNumber': "AMS" }
#    }
# }
mathjax3_config = {
    'tex': {'tags': 'ams'}
}
单行公式引用
单行公式引用需要启用 :nowrap: 选项,并以 MathJax 语法(LaTeX 语法)中的 \label 显式地声明标签。在需要引用时,使用 \ref 引用公式序号,或者使用 \eqref 引用由圆括号括起的公式序号。

LaTeX 中支持的单行公式有两种:

带编号的单行公式: begin{equation}..end{equation}

无编号的单行公式: begin{equation*}..end{equation*}

由于需引用的公式一般都含编号,下面以带编号公式为例。

引用 MathJax 单行公式: \(\ref{mathjax-single}\)\(\eqref{mathjax-single}\)

.. math::
    :nowrap:

    \begin{equation}
    \label{mathjax-single}
    \alpha + \beta = \gamma
    \end{equation}
引用 MathJax 单行公式:
或。

多行公式引用 多行公式需要配合 math 指令的 :nowrap: 选项,并以 MathJax 语法(LaTeX 语法)中的 label 显式地声明标签。

LaTeX 语法中常用的多行公式环境有(不带星号环境将给每行编号,带星号的不做任何编号):

align(*):支持以 & 对齐各列,每行独立编号。列对齐方式在居右与居左之间轮替,即各列的对齐依次是:居右、居左、居右、居左、……

split(*):与 align(*) 类似,但所有行共享一个编号。与 equation-aligned 嵌套环境的效果类似。

gather(*):每行内容居中且独立编号。

gathered:在 equation 内部嵌套 gathered 环境,可以达成居中且共享编号的输出效果。

先看一个 gather 环境的例子,每行独立编号(align 环境也是如此)。要引用的行需要用 label 语法声明一个标签。

类似单行公式引用,引用时使用 \(\ref{mj-gather-a}\) 或者 \(\eqref{mj-gather-a}\)

.. math::
    :nowrap:

    \begin{gather}
    f(x) = x^2 + \sin x \label{mj-gather-a} \\
    S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \}
    \end{gather}
类似单行公式引用,引用时使用
 或者
 。
如果将上例中的 gather 环境改为带星号的 gather 环境,将不进行任何公式编号。此时,标签命令 label 应该写在数学环境内部、第一行公式之前。引用公式

的语法同上。

最后,看一个 split 环境的例子。split 环境中所有行共享同一个编号,引用为

。标签命令同样写在第一行公式之前。

.. math::
    :nowrap:

    \begin{split}
    \label{eq:split}
    a &> b & c &\geq d \\
    e &\neq f & \lim_\infty g &= h
    \end{split}

关于 MathJax 支持的全部 LaTeX 命令,参考 MathJax: Supported TeX/LaTeX commands 文档。

自定义数学命令 MathJax 允许自定义简单的 LaTeX 命令,即 LaTeX 中的 newcommand 命令。参考 MathJax: Defining TeX Macros 页面。

在 Sphinx 中,由于 rst_prolog 变量的存在,我们可以直接在 conf.py 文件中更改该变量值,来在每一个文档文件的头部添加一个额外的数学环境,用于自定义数学命令:

rst_prolog = """
.. math::

   \\newcommand{\\ud}{\\mathop{}\\negthinspace\mathrm{d}}
   \\newcommand{\\pfrac}[2][x]{\\frac{\\partial #2}{\\partial #1}}

.. |section-symbols| replace::
   ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
"""

上例是本文档使用的 conf.py 文件的一部分,定义了两个数学命令:

一个是 ud 命令,无输入参数,用来打印一个竖直的积分符号。

另一个是 pfrac[#1]{#2} 命令,有分子分母两个参数,用来打印偏导分式。参数1是分母,默认值是x;参数2是分子。

下面是一个使用了上述两个自定义符号的例子:

.. math::

    \pfrac{f(x,y)} &= y \\
    \pfrac[y]{f(x,y)} &= \int_0^\pi \sin x \ud x