数学中最常用的关系符号是有作者的,而且他把理由也写了下来。1557 年,罗伯特·雷科德在《The Whetstone of Witte》里第一次把 = 排进铅字,他选择两条平行线的理由是:再没有两样东西能比它们更相等。在 LaTeX 中,这个记号是一族之长:=、\neq、\leq、\approx、\equiv 都是关系符,而真正起作用的与其说是字形,不如说是它们所属的类别。TeX 把它们归入同一个类,统一给出比二元运算符更宽的间距。本页沿着一条线索走完这一族——等号及其近亲、大小记号、否定写法,以及如何把自己的符号提升为关系符——那条线索是:含义由惯例决定,间距却是在源码里声明出来的,而这份声明你可以自己写。
为什么 = 两侧比 + 空得更宽
因为 TeX 是按类别而不是按字形来决定间距的。公式里的每个符号都属于某一类——普通符号、二元运算符、关系符、开括号、闭括号、标点、内部——相邻两者之间的空白,是从一张「类别配对表」里查出来的。像 + 这样的二元运算符两侧填入 \medmuskip,plain TeX 的默认值是 4mu plus 2mu minus 4mu;像 = 这样的关系符则填入 \thickmuskip,默认值是 5mu plus 5mu。也就是说,等号本来就更宽,而且与加号不同,它还留有在需要撑行时伸展的余地。这一切都不需要你手动输入:即使写成一个空格都没有的 a+b=c,排出来的间距依然是对的。
要证明起作用的是类别而不是字形,最干净的例子是一对画出完全相同字符的命令。在 LaTeX 声明数学符号的 fontmath.ltx 里,| 写作 \DeclareMathDelimiter{|}{\mathord}…{symbols}{"6A},而 \mid 写作 \DeclareMathSymbol{\mid}{\mathrel}{symbols}{"6A}——同一套字体的同一个槽位 "6A,区别只在于一个被声明为普通符号、另一个被声明为关系符。把 a | b 和 a \mid b 并排排出来,就会看到同一根竖线周围的空白不同。\| 与 \parallel 也是同样的一对,都在槽位 "6B:\parallel(∥)是关系符,可以陈述「平行于」;而 \| 是普通符号性质的定界符,用于 \|x\| 这样的范数。在这类成对的符号里选错,正是「间距总觉得不对却说不出哪里不对」的最常见原因。
% same glyph, different class: | is ordinary, \mid is a relation
\[ a | b \qquad a \mid b \]
% a bare letter is ordinary; \mathrel promotes it
\[ A R B \qquad A \mathrel{R} B \]
% the colon trap: ":" is a relation, \colon is punctuation
\[ f : A \to B \qquad f\colon A \to B \]所以实用的做法是:自己声明类别。\mathrel{...} 把内容变成关系符,\mathbin{...} 把内容变成二元运算符,二者都是标准 LaTeX 命令。裸写的字母属于普通符号,所以 A R B 会让 R 紧贴两侧;写成 A \mathrel{R} B,它就获得了与 = 相同的间距。反方向的陷阱是冒号。LaTeX 把字符 : 声明为关系符,于是 f : A \to B 会在一个本质上只是标点的冒号两侧塞进关系符的宽间距。\colon 正是为此被声明为 \mathpunct,这也是 f\colon A \to B 成为推荐写法的原因。顺带一提,箭头同样属于关系符类——\to 之所以必须待在数学模式里就是这个缘故——不过它有自己的专页。
\approx、\sim、\simeq、\cong 该用哪一个
一个够用的准则:数值上几乎相等用 \approx(≈),等价关系或「同一数量级」用 \sim(∼),渐近相等与同胚用 \simeq(≃),几何上的全等与代数上的同构用 \cong(≅)。四者都是标准 LaTeX,无需任何宏包。它们长得像并非巧合——每一个都是把等号的严格程度松开了不同的幅度——也正因如此,读者靠的是命令名而不是字形。围绕在它们旁边的还有:表示恒等以及整数同余 a \equiv b \pmod n 的 \equiv(≡)、表示成比例的 \propto(∝)、表示「量级相当」的 \asymp(≍),以及 \doteq(≐)——它的 Unicode 名称是「approaches the limit(趋于极限)」,但不少作者把它读作「按定义等于」。由于 \doteq 和 \asymp 在不同领域读法不一,第一次用到时最好交代清楚。
| 命令 | 字形 | 意义/用途 |
|---|---|---|
= | = | 等号;直接输入——属关系符类 |
\neq | ≠ | 不等于;\ne 相同——标准 LaTeX |
\equiv | ≡ | 恒等相等;同余 a \equiv b \pmod n |
\approx | ≈ | 约等于;数值近似 \pi \approx 3.14 |
\sim | ∼ | 等价关系,或「同一数量级」 |
\simeq | ≃ | 渐近相等;同胚 |
\cong | ≅ | 全等;同构——由 \sim 叠在 = 上拼成 |
\propto | ∝ | 成正比于 |
\asymp | ≍ | 量级相当(分析、数论) |
\doteq | ≐ | = 上加一点;「趋于极限」或「按定义等于」 |
刚才列出的符号里,有三个在任何字体中都不存在。打开 fontmath.ltx 就会看到:\cong 其实是 \mathrel{\mathpalette\@vereq\sim},即把 \sim 叠在 = 上;\doteq 是 \buildrel\textstyle.\over=,把一个句点架在等号上方;\notin 则是在 \in 上重叠打印一道斜线。高德纳的 Computer Modern 里根本没有这几个字形,于是 LaTeX 在排版时现场拼装。这个小知识很有实用价值:拼装出来的符号在更换数学字体时位置会略微移动,而且它们在 PDF 里并不是真正的字符,无法通过复制粘贴取出。如果你在意无障碍阅读或读者要摘录文字,就用 LuaLaTeX 或 XeLaTeX 配合 unicode-math 与 OpenType 数学字体——\cong 会变成真正的 U+2245,\doteq 会变成 U+2250。
\leq 与 \leqslant:≤ 该用哪种字形
两者含义完全相同,区别只在于版式风格,而 \leqslant 要额外付出一个宏包的代价。\leq(≤)与 \geq(≥)属标准 LaTeX,短别名 \le、\ge 指向的是同一个字符。\leqslant(⩽)与 \geqslant(⩾)由 amssymb 提供,把下方那一横画成倾斜的,使它与上方的夹角平行。Unicode 并没有把它们当作「同一字符的两种字体」,而是给了各自的码位——U+2264 less-than or equal to 与 U+2A7D less-than or slanted equal to——可见这份偏好是一项真实存在的惯例,而非一时兴起。因此请为整份文档一次性定下来:同一页里 ≤ 与 ⩽ 混用,在读者眼中不过是排错了字。
表示「远小于」「远大于」的是 \ll(≪)与 \gg(≫),同样是标准 LaTeX。它们各自都是一个整体符号,而不是两个 < 拼出来的,所以别动手去凑。< 和 > 可以直接输入,但只能在数学模式里。若在正文中以默认的 OT1 字体编码写 A<B>C,排出来的会是 A¡B¿C——因为在 OT1 里,这两个位置上放的是倒感叹号和倒问号。若你要表达的顺序不是数值大小——偏序、优先级、加细——惯例上用 prec/succ 一族:\prec(≺)、\succ(≻)以及带等号的 \preceq(⪯)、\succeq(⪰),全部属于标准命令。最后,如果已经决定采用倾斜的不等号,不必逐处改写:在导言区写一行 \let\leq\leqslant,整份文档随即切换,而源码依然清爽可读。
| 命令 | 字形 | 意义/用途 |
|---|---|---|
< | < | 小于;在数学模式中直接输入 |
> | > | 大于;写在正文里会变成 ¿ |
\leq | ≤ | 小于等于;\le 是同一字符——标准 LaTeX |
\geq | ≥ | 大于等于;\ge 是同一字符——标准 LaTeX |
\ll | ≪ | 远小于;单个符号 |
\gg | ≫ | 远大于;单个符号 |
\leqslant | ⩽ | ≤ 的倾斜变体——需要 amssymb |
\geqslant | ⩾ | ≥ 的倾斜变体——需要 amssymb |
\prec | ≺ | 先于;用于非数值大小的顺序 |
\preceq | ⪯ | 先于或等于;\succ ≻ 与 \succeq ⪰ 是其镜像 |
\usepackage{amssymb} % \leqslant, \geqslant, \nleq, \nmid ...
% decide the shape once, in the preamble
\let\leq\leqslant
\let\geq\geqslant
\[ 0 \leq x \leq 1, \qquad n \ll N, \qquad a \prec b \preceq c \]否定怎么写:\neq、\not 与 amssymb
有专用命令就用专用命令——\neq、\notin,以及 amssymb 的 \nleq、\nmid、\nsubseteq 一族——只有在没有专用命令时才退回 \not。不过这里有个意外:在标准 LaTeX 中,\neq 根本不是一个独立字形。fontmath.ltx 里写着 \DeclareRobustCommand\neq{\not=},\ne 的定义与之相同,因此 \not= 与 \neq 的输出连一个字节都不差。所以「宁用 \neq 而不用 \not=」这条老建议,谈的是源码而不是 PDF:\neq 表明了意图,能被搜索命中,也是合作者预期看到的写法。它在迁移到 unicode-math 时也表现更好——在那里 \ne 会变成真正的字符 U+2260,而不是叠印出来的形状。
\not 真正失手的地方,是那些它从未被适配过的符号。它本身是一个字符——符号字体的槽位 "36——以固定的大小、斜度和位置压在后随符号之上,而这套尺寸是按照与 = 差不多宽的记号调校的。遇到较宽的关系符,斜杠就划不到头;遇到较高或形状特别的符号,又会从错误的部位穿过。把 \not\leq 与 \nleq(≰)、\not\subseteq 与 \nsubseteq(⊈)并排一看,专门绘制的 AMS 字形每次都胜出。不过对于没人画过的组合,\not 依然真正有用:并不存在 \nequiv,所以表示不同余的标准写法就是 x \not\equiv y \pmod p。另外要注意,\notin(∉)看着像 AMS 符号,其实完全不需要宏包。
| 命令 | 字形 | 意义/所需宏包 |
|---|---|---|
\neq | ≠ | 不等于;标准 LaTeX(其实展开为 \not=) |
\notin | ∉ | 不属于;标准 LaTeX(在 \in 上重叠打印斜线) |
\nleq | ≰ | 不小于等于;amssymb |
\ngeq | ≱ | 不大于等于;amssymb |
\nsim | ≁ | 不相似;amssymb |
\ncong | ≇ | 不全等/不同构;amssymb |
\nsubseteq | ⊈ | 不是子集;amssymb |
\nparallel | ∦ | 不平行;amssymb |
\nmid | ∤ | 不整除;amssymb |
\nprec | ⊀ | 不先于;amssymb |
把 := 排好,并定义自己的关系符
表示「按定义等于」时,请加载 mathtools 并使用 \coloneqq(≔),而不要直接敲 :=。直接输入的问题不在间距:LaTeX 把 : 声明为关系符,而 TeX 在相邻的两个关系符之间不插入任何空白,所以 := 排出来本就是紧挨着的。问题出在高度上。字符 : 取自正文字体,两点的位置偏低,而 = 跨在数学轴线上,于是冒号看上去像滑下去了。mathtools 提供了抬高冒号的 \coloneqq、左右镜像的 \eqqcolon(=:),以及把文档中所有冒号统一抬高的 centercolon 选项。要注意 \coloneqq 来自 mathtools 而非 amssymb——当 ! Undefined control sequence 指向 \coloneqq 时,多半就是弄混了这一点。
要在关系符上方加东西,经典写法是 \stackrel{\mathrm{def}}{=}。latex.ltx 把它定义为 \mathrel{\mathop{#2}\limits^{#1}},所以无论叠上什么,结果一定是关系符。amsmath 的 \overset 做同样的事,但它不强制变成关系符,而是保留底座符号原本的类别——当底座是二元运算符时,你要的正是它(下方则用 \underset)。至于任何用到两次以上的符号,正确做法是只定义一次,让类别跟着它走:写下 \newcommand{\divides}{\mathrel{|}},你就得到一个间距永远正确的整除记号;日后想改字形,所有出现之处都会跟着变。这一整页其实可以浓缩成一句话——不要在使用处用 \, 或 \; 去补间距,声明类别,把算术交给 TeX。
\usepackage{mathtools} % \coloneqq and \eqqcolon (loads amsmath too)
\newcommand{\divides}{\mathrel{|}}
\[ f(x) \coloneqq x^2 + 1, \qquad y \eqqcolon g(t) \]
% \stackrel always yields a relation; \overset keeps the base class
\[ a \stackrel{\mathrm{def}}{=} b, \qquad a \overset{\mathrm{def}}{=} b \]
\[ 2 \divides 10, \qquad x \not\equiv y \pmod{p} \]