矩阵与数组

把「矩阵(matrix)」一词带进数学的是詹姆斯·约瑟夫·西尔维斯特,时在 1850 年;建立其代数的则是他的朋友阿瑟·凯莱,见于 1858 年《哲学汇刊》第 148 卷所载「A Memoir on the Theory of Matrices」。在 LaTeX 里,矩阵其实并不是什么特殊构造。amsmath 中 pmatrix 的内核就是 \array{*10 c}——一个含十个居中列的 array——外面套上圆括号,再把左右各削去 5pt。这一行代码,正好回答了人们最常带来的两个问题:为什么矩阵到第十一列就不够用了,以及怎样改变列间距。本页涵盖 pmatrixbmatrixvmatrixsmallmatrix 一族,计数器 MaxMatrixColsarray 环境与 \arraycolsep\arraystretch,增广矩阵,以及 \cdots\vdots\ddots

amsmath 只定义了七个矩阵环境

它们是 matrixpmatrixbmatrixBmatrixvmatrixVmatrixsmallmatrix。写上 \usepackage{amsmath} 即可使用。它们都在数学模式中使用,元素横向用 &(和号)分隔,行末用 \\(两个反斜杠)结束。内容的写法完全一样,唯一的区别是外面包裹的定界符。命名也有规律:首字母表示定界符种类——p 是圆括号(parenthesis),b 是方括号(bracket),v 是竖线(vertical bar)。首字母大写的 BmatrixVmatrix 给出「更强」的一对,即花括号和双竖线。而光秃的 matrix 什么都不加。

环境自动添加的定界符典型用途
matrix打算自行添加定界符时的基础
pmatrix圆括号 ( )最常见的矩阵与列向量
bmatrix方括号 [ ]按方括号惯例书写的矩阵
Bmatrix花括号 { }需要花括号时
vmatrix单竖线 | |行列式
Vmatrix双竖线 ‖ ‖范数
smallmatrix无(紧凑型)嵌入正文行内的小矩阵
latex
% preamble: \usepackage{amsmath}
\[
  \begin{pmatrix} a & b \\ c & d \end{pmatrix}
  \quad
  \begin{bmatrix} a & b \\ c & d \end{bmatrix}
  \quad
  \begin{vmatrix} a & b \\ c & d \end{vmatrix}
\]

这七个环境的内容始终居中,无法指定右对齐或左对齐。若想自行决定列的对齐方式,可以使用下文的 array 环境,或者 mathtools 宏包带星版本。mathtools 定义了 matrix*pmatrix*bmatrix*Bmatrix*vmatrix*Vmatrix*smallmatrix*,它们都接受可选参数 [r][c][l],把所有列按该方向对齐(默认为 c)。带星版本来自 mathtools 而非 amsmath,需要 \usepackage{mathtools};由于 mathtools 自身会加载 amsmath,两行不必都写。用 \left\right\big\Big 手动伸缩定界符,则属于另一页「定界符」的范围。

矩阵的列不够用了——MaxMatrixCols 与第十一列的报错

默认上限是 10 列,写到第 11 列就会以 ! Extra alignment tab has been changed to \cr. 中断。TeX 接着解释:You have given more \span or & marks than there were in the preamble to the \halign or \valign now in progress. 读一读就明白:这根本不是「矩阵」的错误,而是 \halign 表格对齐的通用错误。如开头所说,pmatrix 的内核是 \array{*\c@MaxMatrixCols c},而 amsmath.sty 第 1077 行的 \newcount\c@MaxMatrixCols \c@MaxMatrixCols=10 就是列数上限的来源。并没有什么专门针对矩阵的检查在运行,只是把交给 array 的列声明用完了而已。

解决办法是用 \setcounter{MaxMatrixCols}{n} 提高上限。要允许到 20 列,就写 \setcounter{MaxMatrixCols}{20}。数值越大,交给 array 的列声明就越长,TeX 的工作量随之增加,但在 20 左右的量级上,现代环境几乎感觉不到影响。想恢复原状,把它设回 10 即可。另外,这个上限只针对 amsmath 的矩阵环境,对下一节的 array 无效。实测写下 \begin{array}{ccccccccccccccc} 共 15 列,没有任何报错——因为在 array 里,列声明写多少就有多少。

latex
% without this line, an 11th column raises
%   ! Extra alignment tab has been changed to \cr.
\setcounter{MaxMatrixCols}{20}
\[
  \begin{pmatrix}
    a_{1} & a_{2} & \cdots & a_{12}
  \end{pmatrix}
\]

array 环境——自行决定对齐与竖线

array 是一种通用格子,它把列声明作为必需参数接收,每列写一个字母——l 左对齐,c 居中,r 右对齐。在字母之间放一个 |,就会在该位置画出竖线,所以 {l|c|r} 表示三列:左、竖线、居中、竖线、右。它相当于排正文表格的 tabular 的数学版,而且只能在数学模式中使用。若在 \[ \]equation 环境之外写 \begin{array},LaTeX 会试图替你进入数学模式,并报出 ! Missing $ inserted.。元素的分隔与 tabular 一样用 &\\,但每个元素都按文本样式的数学排版。

array 自身不添加定界符,所以要把它当矩阵套上括号,就得手写 \left( … \right)(或 \left[ … \right])。这里可以用测量来验证开头说的「左右各削去 5pt」。把内容都取作 a & b \\ c & d 来量,\left(\begin{array}{cc} … \end{array}\right) 的盒子宽 45.21304pt,而 pmatrix 宽 35.21304pt,差恰好 10pt——正是 array 在列两端加的间距 \arraycolsep(默认 5pt)的两份。amsmath 的矩阵环境在开头和结尾各加一个 \hskip -\arraycolsep 把这份间距抵消掉了。反过来说,改动 \arraycolsep 也会改变矩阵的列间距:实测把它缩到 2pt,pmatrix 宽度变为 29.21304pt;放宽到 10pt,则为 45.21304pt。若想统一拉高行距,用 \renewcommand{\arraystretch}{1.5}——设为 1.5 后,2×2 的总高从 24pt 变成 36pt,正好一倍半(宽度不变)。

latex
% array needs math mode; outside it LaTeX reports "! Missing $ inserted."
\[
  \left(\begin{array}{rrr}
    1 & -2 & 3 \\
    0 & 5 & -1 \\
    4 & 0 & 2
  \end{array}\right)
\]

这个例子的列声明是 {rrr},因此所有列都右对齐-2-1 这类负数元素在右端对齐,读起来清爽。这是 pmatrix(永远居中)做不到的事,也通常正是选用 array 的理由。

增广矩阵——在中间画一条竖线

array 的列声明里放一个 |,再把整体用 \left[ … \right] 括起来。在表示线性方程组的增广矩阵中,惯例是在系数列与常数列之间画一条竖线。bmatrix 之类的 amsmath 矩阵环境不接受列声明,因而画不出这条线——这正是 array 派上用场的地方。只需写一个在系数列与常数列之间带 | 的声明(例如 {cc|c})即可。想用圆括号就换成 \left( … \right),想用花括号则用 \left\{ … \right\}。由于 \left\right 会按内容高度拉伸括号,增加行数也不会走形(拉伸机制本身归另一页「定界符」管)。另外,mathtools 也提供了更顺手的写法来处理这类增广矩阵。

latex
\[
  \left[\begin{array}{cc|c}
    1 & 2 & 5 \\
    3 & 4 & 6
  \end{array}\right]
\]

书写一般的 n×n 矩阵——\cdots\vdots\ddots

把表示省略的点号当作矩阵的一个元素放进去。方向不同的共有四种,按它们落在网格中的位置来选择。它们都是数学模式命令,不需要额外宏包。

  • \cdots居中高度的水平点(⋯),用于沿行的省略。它与 += 同高,很适合横向的排列。
  • \vdots竖直的点(⋮),用于沿列的省略。
  • \ddots — 向右下的斜向点(⋱),用于沿主对角线的省略。
  • \ldots(以及随上下文判断的 \dots)— 基线上的水平点(…),用于数字序列或下标序列。在矩阵内部,通常 \cdots 更合适。
latex
\[
  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}
\]

这就是书写一般 m×n 矩阵的标准写法。第一、二和最后一行中,第三列的 \cdots 填补了 a_{12}a_{1n} 之间的省略;第三行中,各列的 \vdots 表示纵向省略,对角位置的 \ddots 表示向右下的省略——合起来就是说行与列都照此继续。若想让整整一行都是点,amsmath 的 \hdotsfor{n} 会用一排水平点跨过指定的 n 列。

把矩阵嵌进正文行——smallmatrix 恰好占一行

pmatrix 丢进正文的 $ … $ 里,会撑高行高并扰乱周围的行距。看数字就明白原因:在 10pt 排版下,放进 \bigl( … \bigr) 的一个 2×2 矩阵高 14.5pt、深 9.5pt,合计 24.0pt——正好是 12pt 的 \baselineskip 的两倍。amsmath 的 smallmatrix 环境把元素排得小而紧凑,同样的内容放进同样的括号,高 8.5pt、深 3.5pt,合计 12.0pt,也就是恰好一行smallmatrix 不添加定界符,需要的话请手动包裹,例如 \bigl( … \bigr)。(用 \left( \right) 也可以,但在正文中,固定大小的 \bigl\bigr 更不容易扰乱行距。)若已加载 mathtools,还可以使用能选择列对齐的 smallmatrix*

latex
% preamble: \usepackage{amsmath}
Consider the rotation matrix
$\bigl(\begin{smallmatrix} \cos\theta & -\sin\theta \\ \sin\theta & \cos\theta \end{smallmatrix}\bigr)$
in the plane.