粉笔写不出粗体。于是在二十世纪中叶的讲堂里,数学家开始把某些笔画重描一遍,用加倍的线条代替粗体。这个黑板上的习惯后来被刻成了铅字,就是黑板粗体——今天印刷品上 ℝ、ℕ、ℤ 的祖先。LaTeX 提供四套装饰字母:花体 \mathcal、手写体 \mathscr、哥特体 \mathfrak 和黑板粗体 \mathbb。麻烦的是,最多人要用的 \mathbb 并不内置,而内置的 \mathcal 遇到小写字母时不但不报错,还会默默排出一个完全不同的符号。本页要做的,就是把这四套分清楚,并且用得不出事。
\mathcal、\mathscr、\mathfrak、\mathbb 有什么区别
四者的区别只在于调用哪一套字体,以及那套字体里究竟收了多少字符。而本页的关键在于:\mathcal{A} 并不是把 A 转换成花体字母的命令。它改变的只是参数范围内所用数学字体的「族」,字符的位置(槽位)原封不动。也就是说,A 依然是「当前字体的第 65 号字符」这条指令,只是被投进了另一套字体——那个槽位里放着什么,排出来的就是什么。这四套装饰字母上出的事故,几乎都源于这一点。
| 命令 | 外观 | 需要的宏包 | 收录的字符 |
|---|---|---|---|
\mathcal | 流畅的花体大写 | 无需(内置) | 仅大写 A–Z |
\mathscr | 倾斜明显的正式手写体 | mathrsfs(另一系为 eucal) | 仅大写 A–Z |
\mathfrak | 棱角分明的哥特体 | amssymb 或 amsfonts | 大写、小写与数字 |
\mathbb | 笔画加倍的粗体 | amssymb 或 amsfonts | 仅大写 A–Z(外加 \Bbbk) |
看表就会发现两处不对称:只有 \mathcal 是内置的,也只有 \mathfrak 带小写。下文的绝大多数陷阱都可以由这两点解释。先从被搜索得最多的问题开始:ℝ 到底怎么打出来?
如何打出 ℝ、ℕ、ℤ——以及 \mathbb 为何需要 amssymb
在导言区写上 \usepackage{amssymb},正文里写 $\mathbb{R}$——就这么简单。用 amsfonts 也能得到同一个 \mathbb(amssymb 内部会加载 amsfonts)。忘记加载就会以 ! Undefined control sequence. 中断。原生 LaTeX 里根本不存在黑板粗体,所以这不是配置出错,而是设计如此。
\usepackage{amssymb} % gives \mathbb, \mathfrak and \Bbbk
% ...
\[
\mathbb{N} \subset \mathbb{Z} \subset \mathbb{Q}
\subset \mathbb{R} \subset \mathbb{C}
\]为什么不内置?因为这是 Knuth 的偏好。黑板粗体大约起于 1950 年代末的法国,1960 年代初在普林斯顿大学数学系扎下根;1960 年代中期进入印刷品,Gunning 与 Rossi 的 Analytic Functions of Several Complex Variables(1965)是早期例子之一。而 Knuth 认为粗体就该用真正的粗体,因此在他为 TeX 设计的 Computer Modern 中 有意不收 黑板粗体。这个空缺由 AMS 在 1985 年补上:他们为 AMS-TeX 做了一套粉笔风格的黑板粗体,当时的命令叫 \Bbb。这个名字至今还留在 amsfonts.sty 里,作为一个指向 \mathbb 的过时别名。顺带一提,Jean-Pierre Serre 讲课时用黑板粗体,出版物里却始终使用普通粗体。
\mathbb{R}— 全体实数 ℝ。\mathbb{C}— 全体复数 ℂ。\mathbb{Z}— 全体整数 ℤ,来自德语 Zahlen(数),一般归于 Hilbert;已知最早的教科书用例是 Bourbaki 的 Algèbre(1947)。\mathbb{Q}— 全体有理数 ℚ。\mathbb{N}— 全体自然数 ℕ。\mathbb{F}_q— 含 q 个元素的有限域;下标保持普通斜体。
\mathbb{k} 排出来是 ℸ——小写要用 \Bbbk
千万别把小写字母交给 \mathbb。想要黑板粗体的小写 k 而写下 \mathbb{k},得到的是希伯来字母 daleth ℸ,既没有警告也没有报错。这正是上一节的原理:k 仍旧是「第 107 号槽位」这条指令,它被交给 msbm 字体,而那个槽位上坐着的是 \daleth。同理,\mathbb{a} 会变成翻转的 G,即 ⅁(\Game),\mathbb{1} 会变成 ⊮(\nVdash)。这些写法都能正常编译通过,所以在你亲眼看 PDF 之前不会有任何提示。
% lowercase blackboard bold is its own command, not \mathbb{k}
\[
\Bbbk = \overline{\Bbbk}, \qquad V \otimes_{\Bbbk} W
\]正确写法是 \Bbbk。amssymb 把黑板粗体的小写 k 作为一个独立符号 提供,这正是把域记作 k 的代数文档所需要的。注意它不带参数:是 \Bbbk,不是 \mathbb{k}。若还需要别的小写字母或数字(黑板粗体的 1、2,小写 h 等),就得借助别的字体宏包。dsfont 通过 \mathds 提供大写以及 h、k 和数字 1;bbm 通过 \mathbbm 提供小写和数字;bbold 则直接重定义 \mathbb,覆盖范围大得多。最后这个会与 amssymb 冲突,因此若要在同一文档里同时加载,先决定由谁来定义 \mathbb。
\mathcal 只有大写——\mathcal{a} 会变成 ⊣
\mathcal 的参数请限定在大写 A–Z。写 \mathcal{a} 得到的不是变形的花体 a,而是毫不相干的 ⊣(\dashv),而且连一句警告都没有。\mathcal 的定义是 \DeclareSymbolFontAlphabet{\mathcal}{symbols},也就是切换到数学符号字体 cmsy10;那套字体把花体大写放在第 65–90 号槽位上,而小写和数字的位置塞着完全不同的符号。更要命的是那套字体 每个槽位都是满的,TeX 根本没有机会说「没有这个字符」,只能默默排出它找到的那个邻居。
| 你写的 | 实际排出 | 该槽位上的符号 |
|---|---|---|
\mathcal{a} | ⊣ | \dashv |
\mathcal{b} | ⌊ | \lfloor |
\mathcal{g} | } | \rbrace |
\mathcal{o} | ≀ | \wr |
\mathcal{1} | ∞ | \infty |
\mathcal{2} | ∈ | \in |
按同样的道理,\mathcal{Hom} 排不出「Hom」这个词,也不是三个花体字母:只有 H 是花体,而 o 和 m 分别变成 ≀ 和 ⇕。请记住,装饰字母命令的参数被当作 一串符号,而不是一个单词。实用准则很简单:给 \mathcal 的永远只是一个大写字母。集合族的 \mathcal{A}、傅里叶变换的 \mathcal{F}、σ 代数的 \mathcal{B}、整数环的 \mathcal{O}——这才是它该有的用法。
\mathcal 与 \mathscr 的区别——加载 mathrsfs
\mathcal 是内置 cmsy10 的花体字母,\mathscr 则是由 \usepackage{mathrsfs} 载入的 rsfs10 手写体。两者并排一看便知不同:\mathcal 字身宽、装饰笔画克制;\mathscr 向右倾斜得多,粗细对比鲜明,是一套正式的手写体——拉普拉斯变换的 \mathscr{L} 或拉格朗日量的 \mathscr{L} 通常都用它。若想在同一篇论文里区分两套装饰字母,这个组合最省事。
\usepackage{mathrsfs} % adds \mathscr (RSFS); \mathcal is left alone
% ...
\[
\mathcal{F} \subset \mathcal{P}(X), \qquad
\mathscr{L}\{f\}(s) = F(s)
\]RSFS 是 Ralph Smith’s Formal Script 的缩写。加州大学圣迭戈分校的物理学家 Ralph Smith 用 Metafont 绘制了它,1.0 版发布于 1991 年 10 月。随字体附带的 README 中他写道,自己是照着 R. Hunter Middleton 设计的一款正式手写体临摹的,而后者又源自十八世纪盛行的 Spencerian/Copperplate 手写体。同一份 README 里他还说,希望有朝一日补上小写字母,做成一套正文字体——这次修订始终没有发生。所以直到今天,写下 \mathscr{a} 仍会在日志里得到这句:Missing character: There is no a in font rsfs10!
这一行其实是好消息。\mathcal 会默默换成别的符号,而 \mathscr 会老老实实报告缺字:rsfs10 里只有大写,所以 TeX 能够如实说出「没有」。\mathscr 还有另一个来源,即 eucal 宏包调用的 Euler Script。Euler 是 Hermann Zapf 受 AMS 委托于 1980–81 年绘制的字体,试图再现数学家在黑板上手写的样子——也就是直立而非倾斜。它的神情与 RSFS 那种大幅倾斜的古典手写体截然不同。
| 加载方式 | 得到的命令 | 排出的字体 |
|---|---|---|
\usepackage{mathrsfs} | \mathscr(\mathcal 不受影响) | RSFS |
\usepackage[scr]{rsfso} | \mathscr | 倾斜更平缓的 RSFS |
\usepackage[mathscr]{eucal} | \mathscr(\mathcal 不受影响) | Euler Script |
\usepackage{eucal} | 替换掉 \mathcal | Euler Script |
\usepackage{calrsfs} | 替换掉 \mathcal | RSFS |
表的下半部分正是陷阱所在。calrsfs 和不带选项的 eucal 会 直接覆盖 \mathcal。「我的 \mathcal 突然换了样子」「和合作者编出来的字不一样」这类问题,相当一部分都能追溯到有人加了这两个宏包之一。此外,若同时加载 mathrsfs 和带 mathscr 选项的 eucal,后加载的那个会抢走 \mathscr,排出你没选过的字体。手写体只用一个来源——这是唯一可靠的防守。
\mathfrak 为什么是理想与李代数的字母
\mathfrak 同样由 amssymb(或 amsfonts)提供,但它是四者中唯一 大写、小写、数字一应俱全 的。也只有这套字体,日常唱主角的是小写字母。理想写作 \mathfrak{p}(素理想)、\mathfrak{m}(极大理想)、\mathfrak{a};李代数写作 \mathfrak{g}、\mathfrak{h}、\mathfrak{sl},好让它们与对应的李群 G、H 一眼分开。
为什么偏偏是哥特体?原因不在数学,而在印刷史。十九世纪的德国,德语书籍通常就用哥特体排版。1876 年,Richard Dedekind 在为 Dirichlet《Vorlesungen über Zahlentheorie》第三版所写的补篇中,把 Kummer 的理想数替换成具体的数集,并命名为「理想」。哥特体正是当时德国排字工手边现成的对照字体,于是理想就用哥特体小写来写。如今德语印刷早已弃用这套字,只有代数的记号还替它保存着这个习惯。
\usepackage{amsmath,amssymb} % amssymb: \mathfrak — amsmath: \operatorname
% ...
\[
\mathfrak{g} = \operatorname{Lie}(G), \qquad
\mathfrak{p} \subset \mathfrak{m} \subset \mathcal{O}
\]顺带一提,amssymb 调用的哥特体并非十九世纪的原版活字,而是 Hermann Zapf 作为 AMS Euler 一部分绘制的 Euler Fraktur(字体名 eufm10)。可读性已大为改善,但笔画繁密这一点没变。在下标里、或任何字号变小的位置大量使用 \mathfrak,\mathfrak{p} 和 \mathfrak{q} 就会分不清。字号一小,要么换用别的符号,要么在正文里把字母的读法交代一次。
XeLaTeX 与 LuaLaTeX:unicode-math 的 \symbb
若在 XeLaTeX 或 LuaLaTeX 上使用 unicode-math,这四套装饰字母都由同一款 OpenType 数学字体提供,用 \symbb、\symcal、\symscr、\symfrak 调用。由于选中的是 Unicode 字符本身,本页大半陷阱随之消失:\symbb{k} 确实排出 𝕜,也不必再记住 \Bbbk。不过实际得到什么,取决于所选数学字体收了多少字形——例如 \symcal 与 \symscr 能否排成不同的样子,就是字体本身的功能。按引擎该怎么选,留给「数学字体」那一页。
% XeLaTeX or LuaLaTeX only
\usepackage{unicode-math}
\setmathfont{Latin Modern Math}
% ...
\[
\symbb{R}, \quad \symcal{F}, \quad \symscr{L},
\quad \symfrak{g}, \quad \symbb{k}
\]