书法体与花体

粉笔写不出粗体。于是在二十世纪中叶的讲堂里,数学家开始把某些笔画重描一遍,用加倍的线条代替粗体。这个黑板上的习惯后来被刻成了铅字,就是黑板粗体——今天印刷品上 ℝ、ℕ、ℤ 的祖先。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棱角分明的哥特体amssymbamsfonts大写、小写与数字
\mathbb笔画加倍的粗体amssymbamsfonts仅大写 A–Z(外加 \Bbbk

看表就会发现两处不对称:只有 \mathcal 是内置的也只有 \mathfrak 带小写。下文的绝大多数陷阱都可以由这两点解释。先从被搜索得最多的问题开始:ℝ 到底怎么打出来?

如何打出 ℝ、ℕ、ℤ——以及 \mathbb 为何需要 amssymb

在导言区写上 \usepackage{amssymb},正文里写 $\mathbb{R}$——就这么简单。用 amsfonts 也能得到同一个 \mathbbamssymb 内部会加载 amsfonts)。忘记加载就会以 ! Undefined control sequence. 中断。原生 LaTeX 里根本不存在黑板粗体,所以这不是配置出错,而是设计如此。

document.tex
\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 之前不会有任何提示。

document.tex
% lowercase blackboard bold is its own command, not \mathbb{k}
\[
  \Bbbk = \overline{\Bbbk}, \qquad V \otimes_{\Bbbk} W
\]

正确写法是 \Bbbkamssymb 把黑板粗体的小写 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} 通常都用它。若想在同一篇论文里区分两套装饰字母,这个组合最省事。

document.tex
\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}替换掉 \mathcalEuler Script
\usepackage{calrsfs}替换掉 \mathcalRSFS

表的下半部分正是陷阱所在。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 的理想数替换成具体的数集,并命名为「理想」。哥特体正是当时德国排字工手边现成的对照字体,于是理想就用哥特体小写来写。如今德语印刷早已弃用这套字,只有代数的记号还替它保存着这个习惯。

document.tex
\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 能否排成不同的样子,就是字体本身的功能。按引擎该怎么选,留给「数学字体」那一页。

document.tex
% 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}
\]