3.10. 使用数学表达式#

在网页中显示数学表达式现在已经比较容易了,但这个问题远非看上去那么简单。 与之类似,现在 Sphinx 缺省支持数学表达式,可以不用做什么额外的配置就可以很好地渲染数学表达式; 但稍微扩展一下就会发现这背后涉及到很多方面的技术。

上面指的是渲染的问题。在涉及到数学表达式的输入方面,也是一个令初学者望而生畏的难点; 不过好在有很多的案例可以模仿。

使用数学符号和公式的最简单方法是用 Sphinx 本身的指令进行模拟。 例如上标的效果,使用 sub 表示平方等符号:

语法如下:

I\ :sup:`2`\ C

效果如: I2C

reStructuredText 中支持的数学表达式使用 LaTeX 语法。 对使用 LaTeX 书写数学表达式不熟悉的读者可以在网络上找到许多入门语法。 一个相对简单的数学表达式列表 https://ikerdocs-sphinx.readthedocs.io/syntax/math.html

对于稍微复杂点的数学表达式可使用Sphinx中对数学表达式的支持,下面介绍使用方法。 数学表达式主要有两种格式,行内与行间。

3.10.1. 行内数学表达式#

行内数学表达式是内嵌于文本中,不单独成行的表达式。直接使用角色 :math: , 例如 :math:`sin\alpha` ,效果 \(sin\alpha\)

行内数学表达式示例

公式前文字 :math:`sin\alpha` 公式后文字。

行内数学表达式显示效果

公式前文字 \(sin\alpha\) 公式后文字。

3.10.2. 行间数学表达式#

行间数学表达式是指独立成行的表达式。 reStructuredText 语法中使用 math 指令( Directive: math )来插入行间数学表达式。

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

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

(3.10.1)#\[a + b = c\]

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

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

关于 Sphinx 中的数学表达式使用:

备注

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

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

行间数学表达式示例代码

.. math::
    f'(x) = \lim_{\triangle x \to 0} \frac{f(x + \triangle x) - f(x)}{\triangle x}

行间数学表达式显示效果:

(3.10.2)#\[f'(x) = \lim_{\triangle x \to 0} \frac{f(x + \triangle x) - f(x)}{\triangle x}\]

3.10.3. 数学表达式编号与引用#

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

常规方式

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

单行公式的例子如下。使用 :eq:`math-single` 引用时会显示 Eq.3.10.3 这个链接。

.. math::
    :label: math-single

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

使用 &\\ 进行标记的对齐多行公式,引用如 Eq.3.10.4

.. math::
    :label: math-multi

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

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

.. math::

    f(x) = x^2 + \sin x

    S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \}
(3.10.5)#\[ \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*}

无编号多行居中:

\begin{gather*} f(x) = x^2 + \sin x \\ S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \} \end{gather*}

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

3.10.4. 使用Latex声明 Label 方式#

警告

在 HTML 输出中存在问题。感觉是在 Latex 环境中使用的。需要进一步测试。

单行公式引用#

单行公式引用需要启用 :nowrap: 选项,并以 MathJax 语法(LaTeX 语法)中的 \label 显式地声明标签。 在需要引用时,使用 \ref 引用公式序号,或者使用 \eqref 引用由圆括号括起的公式序号。

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

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

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

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

引用 MathJax 单行公式: :math:`\ref{mathjax-single}`:math:`\eqref{mathjax-single}`.. math::
    :nowrap:

    \begin{equation}
    \label{mathjax-single}
    \alpha + \beta = \gamma
    \end{equation}

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

\begin{equation} \label{mathjax-single} \alpha + \beta = \gamma \end{equation}

多行公式引用#

警告

在 HTML 输出中存在问题。感觉是在 Latex 环境中使用的。需要进一步测试。

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

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

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

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

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

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

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

类似单行公式引用,引用时使用 :math:`\ref{mj-gather-a}` 或者 :math:`\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}

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

\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 应该写在数学环境内部、第一行公式之前。引用公式 \(\ref{eq:gatherstar-a}\) 的语法同上。

\begin{gather*} \label{eq:gatherstar-a} f(x) = x^2 + \sin x \\ S(r) = \{ x \in \mathbb{R}^n \,|\, \|x\| \leq r \} \end{gather*}

最后,看一个 split 环境的例子。split 环境中所有行共享同一个编号,引用为 \(\ref{eq:split}\) 。标签命令同样写在第一行公式之前。

.. math::
    :nowrap:

    \begin{split}
    \label{eq:split}
    a &> b & c &\geq d \\
    e &\neq f & \lim_\infty g &= h
    \end{split}
\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 文档。