二元运算符

「我不喜欢用 × 表示乘法,因为它太容易和字母 x 混淆。」1698 年,莱布尼茨在给约翰·伯努利的信里这样写道。每当你在 LaTeX 里犹豫该敲 \times 还是 \cdot——两者都是本页要讲的二元运算符——你其实就在为一场延续了三百多年的争论选边。不过这里真正的主题并不是字形。TeX 会把公式中的每一个符号归入某个类,前后的间距完全由这个类决定;正因如此,$+1$ 里的 +$a+1$ 里的 + 明明是同一个字符,排出来的宽度却不一样。本页通盘梳理 \times\div\cdot\pm\oplus\cup\setminus 这些运算符,说明哪些需要 amssymb,并给出 TeX 判断失误时用 \mathbin 纠正的办法。

\cdot\times 的区别:乘号该用哪一个

默认用 \cdot(⋅)。公式里数与数、量与量相乘时用中点,把 \times(×)留给向量的叉积、笛卡儿积、维数记法(3 \times 3 矩阵)以及十的幂(6.02 \times 10^{23})。这种分工正是从莱布尼茨的抱怨里长出来的。把 × 印上书页并让它流行起来的是威廉·奥特雷德,见于 1631 年伦敦出版的《Clavis Mathematicae》;可是在代数里,x 又恰恰是未知数最常用的名字。于是在 1698 年 7 月 29 日的信中,莱布尼茨否掉了这个叉号,改而建议在两个量之间点一个点。赢的是他。今天的数学著作里几乎见不到表示乘法的 ×,原因就在这里。

除号 \div(÷)也有一段类似的经历。这个符号叫 除号线(obelus),最早把它用于除法的是约翰·拉恩,见于 1659 年的《Teutsche Algebra》。然而规定科技领域数学记法的 ISO 80000-2 标准明确指出:除法应使用斜线 / 或分数线,比则使用冒号 :,而 ÷ 不应使用。实用结论很简单——论文和技术文档里写 \frac{a}{b},不写 \div\div 的用武之地大概只剩下基础教育教材和计算器。还有一个坑:用句点代替 \cdot 写成 a.b 是行不通的。TeX 不把句点当作运算符,两侧不加间距,在 10pt 文档中实测 $a.b$ 为 12.36pt,而 $a \cdot b$ 为 16.80pt——看上去像小数点而不是乘号。反过来,直接敲 * 却没有问题:数学模式下的 *\ast 是同一个二元运算符,排出来完全一致。

latex
% \cdot for ordinary products; \times for cross products, dimensions, powers of ten
\[ 2 \cdot 3 = 6, \qquad \mathbf{u} \times \mathbf{v}, \qquad 6.02 \times 10^{23} \]
% a period is not a multiplication dot: it gets no operator spacing
\[ a.b \qquad a \cdot b \]
% in scientific writing prefer a fraction to the obelus
\[ \frac{a}{b} \qquad a \div b \]
命令字形含义/使用场合
\pm±正负号;x = a \pm b
\mp负正号;与 \pm 符号相反
\times×叉积、笛卡儿积、维数、十的幂
\div÷除号线;科技写作建议改用 \frac
\cdot默认乘号;数乘与点积
\ast卷积等;与数学模式下的 * 相同
\star五角星;常用来表示自定义的乘法
\circ函数复合;g \circ f
\bullet实心圆点;表示比 \circ 更重的运算
\diamond菱形运算符

为什么只有 $+1$ 里的 + 挤在一起

二元运算符是连接左右两边的符号,因此一旦某一侧没有可连接的东西,TeX 就判定它根本不是二元运算符。排在式首的 + 会被降格为符号(一元),两侧不加任何间距。看数字最清楚:在 10pt 文档中 $+1$ 宽 12.78pt;而写成 ${}+1$,前面放一对空花括号,+ 就有了左操作数,重新成为真正的二元运算符,宽度涨到 17.22pt。相差的 4.44pt,正是每侧 2.22pt。这 2.22pt 来自参数 \medmuskip(默认 4mu plus 2mu minus 4mu),它比关系符使用的 \thickmuskip5mu plus 5mu,每侧 2.78pt)窄——所以 $a=b$ 排得比 $a+b$ 松。无论你在源文件里敲多少个空格,输出都不会变。决定间距的只有类。

这套机制也会在意想不到的地方反噬:花括号会抹掉符号的类。$a\times b$ 宽 21.80pt,可一旦写成 $a{\times}b$,立刻缩到 17.36pt——被括起来的内容会被当作一个整体的普通符号(Ord 类),从此忘记自己曾是二元运算符。如果你自己写的宏出现「偏偏这个符号间距不够」的毛病,原因基本就在这里。补救办法是用 \mathbin{...} 包住:$a\mathbin{\times}b$ 又回到 21.80pt,与原本的 $a\times b$ 完全一致。反过来,想去掉间距就用 \mathord{...},想当作关系符来排就用 \mathrel{...}——$a\mathrel{\times}b$ 排出来是 22.91pt,恰好等于 $a=b$ 的宽度。

latex
% a leading + has nothing to bind: TeX makes it a sign and sets it tight
% an empty group gives it a left operand and the medium space comes back
\[ +1 \qquad {}+1 \]
% braces strip the class; \mathbin puts it back, \mathrel makes it a relation
\[ a \times b \qquad a {\times} b \qquad a \mathbin{\times} b \qquad a \mathrel{\times} b \]
% always declare the class when you define an operator of your own
\newcommand{\op}{\mathbin{\triangle}}
\[ x \op y \]
命令强制的类每侧添加的间距(10pt 正文)
\mathbin二元运算符2.22pt(\medmuskip = 4mu)
\mathrel关系符2.78pt(\thickmuskip = 5mu)
\mathord普通符号(Ord)无;与用花括号包住的效果相同

圆圈与方框运算符:哪些需要 amssymb

带圆圈的都是 LaTeX 标准,带方框的一律需要 amssymb——一句话基本就说完了。直和 \oplus(⊕)、张量积 \otimes(⊗)、用于阿达马积一类的 \odot(⊙),连同 \ominus\oslash\bigcirc,不加载任何宏包就能用。而方框一族——\boxplus(⊞)、\boxminus(⊟)、\boxtimes(⊠)、\boxdot(⊡)——以及圆圈里由 AMS 追加的 \circledast(⊛)、\circledcirc(⊚),都以导言区的 \usepackage{amssymb} 为前提。忘了加载,排版就会停在 ! Undefined control sequence.。至于该挑哪一个,依据是惯例:加法性的运算用 ⊕,乘法性的运算用 ⊗。范畴论和表示论的文献几乎无一例外都按这个读法来。

命令字形宏包含义/用途
\oplus直和;加法性运算
\ominus圆圈减号
\otimes张量积;乘法性运算
\oslash圆圈斜线;逐元素除法
\odot阿达马积、逐元素乘积
\bigcirc大圆
\circledastamssymb圆圈星号
\circledcircamssymb圆圈套圆
\boxplusamssymb方框加号
\boxminusamssymb方框减号
\boxtimesamssymb方框乘号
\boxdotamssymb方框点
latex
% circled operators are standard; boxed ones come from amssymb
\usepackage{amssymb}
% ...
\[ V \oplus W, \qquad u \otimes v, \qquad A \boxplus B \]

形状虽然相同,但 \bigoplus(⨁)、\bigotimes\bigodot\biguplus 这些放大版并不是二元运算符。它们与求和号 \sum 同属大型运算符,上下可带上下标,且在行内与行间公式中大小不同。想把 \oplus 放大时,用 \Large 之类硬撑会让上下标错位,务必改用 \bigoplus。详情见「和、积分与大型运算符」一页。

集合与格的运算符:\cup\cap\setminus

本节的角色全是 LaTeX 标准符号,不需要额外宏包。交集 \cap(∩)、并集 \cup(∪)、多重集之和 \uplus(⊎)、差集 \setminus(∖)。在格与序集里会遇到方形的 \sqcap(⊓)、\sqcup(⊔);在逻辑里则是 \wedge(∧)、\vee(∨),后两者还有别名 \land\lor。字形完全相同——区别只在于逻辑语境下这两个名字读起来更贴切。这里最常见的事故,是把差集写成 \backslash。这个命令属于普通符号(Ord 类),拿不到二元运算符的间距:10pt 下实测 $A \backslash B$ 为 20.59pt,而 $A \setminus B$ 为 25.03pt——每侧差了 2.22pt。差集请一律用 \setminus。若加载了 amssymb,还可以选用更细的 \smallsetminus(∖)。

命令字形宏包含义/用途
\cap交集
\cup并集
\uplus多重集之和、不交并
\sqcap格的 meet(下确界)
\sqcup格的 join(上确界)
\wedge逻辑与、meet;别名 \land
\vee逻辑或、join;别名 \lor
\setminus差集;不能用 \backslash 代替
\wr圈积
\smallsetminusamssymb更细的差集号
\Capamssymb双重交
\Cupamssymb双重并
latex
% a set difference needs \setminus, not \backslash
\[ A \setminus B \qquad A \cup (B \cap C) \]
% \land and \lor are aliases of \wedge and \vee
\[ p \wedge q \iff p \land q \]

其余运算符,以及 \lhd not provided in base LaTeX2e 报错

剩下的是些零散符号,但个个都有用武之地。余积、不交并的 \amalg(⨿),表示伴随与对偶的 \dagger(†)和 \ddagger(‡),用于正规子群与群作用的 \triangleleft(◁)、\triangleright(▷)——都属 LaTeX 标准。再加上 amssymb 那边的常客:群论中的半直积 \ltimes(⋉)、\rtimes(⋊),用于转置的 \intercal(⊺),带点的 \dotplus(∔),以及 \divideontimes(⋇)。写代数方面的文档,迟早都要用到半直积,所以一开始就在导言区放上 \usepackage{amssymb} 反而更省事。

命令字形宏包含义/用途
\amalg⨿余积、不交并
\dagger剑标;伴随、共轭转置
\ddagger双剑标
\triangleleft左三角;正规子群等
\triangleright右三角;群作用等
\dotplusamssymb带点加号
\intercalamssymb作上标表示转置
\ltimesamssymb左半直积
\rtimesamssymb右半直积
\divideontimesamssymb带点乘号
\lhdlatexsym / amssymb较粗的左三角;纯 LaTeX 下不可用
\rhdlatexsym / amssymb较粗的右三角

最后两行藏着一个坑。想用更粗的记号写正规子群而敲下 \lhd,纯 LaTeX 会停在 ! LaTeX Error: Command \lhd not provided in base LaTeX2e.\lhd\rhd\unlhd\unrhd 这几个名字只是在内核里被预留了,符号本体在别的宏包里。加载 \usepackage{latexsym}\usepackage{amssymb} 中的任意一个,四个就都能用;若你本来就加载了 amssymb,则无需任何改动。反过来说,如果标准的 \triangleleft(◁)已经够用,你根本不会撞上这个错误。

自己定义运算符时,请回想本页开头关于类的那段话。像 \newcommand{\op}{\mathbin{\triangle}} 这样把类写明,此后只要敲 x \op y,两侧的间距 TeX 就会替你照管好。忘记指定类的宏会被当作普通符号(Ord),于是每用一次就得手动补一个 \,。在添加符号之前先定好类——围绕二元运算符的间距事故,基本靠这一步就能避免。