理工科数学有一套国际约定,规定哪些内容排成斜体、哪些排成直立体(罗马体),这套约定就是 ISO 80000-2,在日本被采用为 JIS Z 8000-2。规则本身一句话就能说完:会变的量用斜体,含义固定的用直立体。然而在 LaTeX 中照常书写时,这些规则会清晰地分成两堆。\sin、\partial 和数字默认就已正确,而 自然对数的底 e、虚数单位 i、微分的 d、圆周率 π 默认都是斜体——也就是不合规。本页梳理标准的要求,以及如何用 \mathrm{d}x、\uppi、isomath 和 unicode-math 的 math-style=ISO 让 LaTeX 达成合规,并通过从 PDF 中取出实际字符编码来核实结果。
ISO 80000-2 与 JIS Z 8000-2(原 JIS Z 8201)
ISO 80000-2(Quantities and units — Part 2: Mathematics)是同时规定数学符号含义与 排版方式(书体)的国际标准。现行文本为 2019 年第二版(第一版为 2009 年),并于 2021 年 11 月发布了更正版。日本以等同标准的形式采用了它:JIS Z 8000-2:2022「量及单位—第2部:数学记号」于 2022 年发布,而沿用四十余年的 JIS Z 8201:1981 则在 2022 年 3 月 22 日废止。旧教科书和企业内部规范中仍会出现 JIS Z 8201,或其源头 ISO 31-11,但今天应依据的是 ISO 80000-2 / JIS Z 8000-2。
为什么标准要管到书体?因为在数学中,书体本身承载含义。e 视上下文既可能是变量 e,也可能是自然对数的底 2.718…;把变量写成斜体、把常数写成直立体,读者无需注释即可区分。标准把这种区别固定为全球通用规则,使论文、教材与技术文档之间的记法不发生漂移——而这种漂移会造成实际损害:若量的符号与单位符号共用一种书体,谁也说不清 m 是质量还是米。用 LaTeX 排数学是遵守标准的良好起点,因为在数学模式中字母会自动倾斜,而 \sin 这类函数名和普通数字从一开始就是直立体。
核心规则 —— 会变的用斜体,固定的用直立体
标准的核心只有一个想法:值会随上下文变化的量用斜体;含义或数值唯一固定的用直立体。 像 x、y 这样的变量,像 a、b 这样暂时视为常数的参数,以及一般函数符号 f、g,其值都不固定,所以都用 斜体——而这恰好就是 LaTeX 数学模式的默认行为,因此不必额外做什么就已合规。另一边,数值确定的 数学常数(e、i、π)、微分运算符 d 及其相关符号(偏微分 ∂ 等)、系统定义的函数名(sin、exp、ln、Γ),以及 数字 和 单位符号,都用直立体。标准的立场很简单:既然这些都不是变量,就不得使用变量的书体。
遇到拿不准的情况时,最快的检验是:这个符号能不能改名为另一个字母? 把 x 改成 t,公式的含义不变——所以它是变量,用斜体。但积分 dx 中的 d 不能换成别的字母;它是含义固定的运算符,因此用直立体。同一检验也解释了为什么 \sin 中的 s 不能替换,\mathrm{kg} 中的 k 也不能替换。
直立体与斜体速查 —— LaTeX 的默认能走多远
先说结论:LaTeX 默认已经满足函数名、偏微分符号 ∂、数字和大写希腊字母,而 需要你自己处理的是 e、i、π、微分运算符 d、单位以及向量/张量。下表中「默认 OK」表示普通数学模式已按标准排版,「需要处理」表示必须显式改成直立体——或粗斜体。
| 对象 | 标准规定的书体 | LaTeX 中的写法 |
|---|---|---|
variables | 变量与量 x, y, t 为斜体 | x(数学模式默认 — OK) |
parameters | 参数与一般函数 a, b, f, g 为斜体 | a, f(x)(默认 — OK) |
\mathrm{e} | 自然对数的底 e 为直立体 | \mathrm{e}。普通 e 为斜体,不合规。需要处理 |
\mathrm{i} | 虚数单位 i(电气工程中为 j)为直立体 | \mathrm{i} / \mathrm{j}。需要处理 |
\uppi | 作为常数的 π 为直立体 | \uppi(来自 upgreek 或 unicode-math)。普通 \pi 为斜体。需要处理 |
\mathrm{d} | 微分运算符 d 为直立体 | \mathrm{d}x。普通 d 为斜体,不合规。需要处理 |
\partial | 偏微分符号 ∂ 为直立体 | \partial(默认已是直立体 — OK) |
\sin | 已定义函数 sin, exp, ln 为直立体 | \sin, \exp, \ln(默认已是直立体 — OK) |
\Gamma | 作为函数名的大写希腊字母 Γ 为直立体 | \Gamma(标准 LaTeX 默认直立 — OK;但请参见下节) |
digits | 数字 0–9 为直立体 | 123(默认已是直立体 — OK) |
\unit | 单位符号 m, kg, s 为直立体 | siunitx 的 \unit{} / \qty{}{}。需要处理 |
\vectorsym | 向量与矩阵 a, A 为粗斜体 | \bm{a},或 isomath 的 \vectorsym{a}。需要处理 |
\tensorsym | 张量 T 为无衬线粗斜体 | isomath 的 \tensorsym{T}。需要处理 |
\mathrm{d}x —— 让微分的 d 与常数 e、i 变成直立体
对最常见问题的回答很短:用 \mathrm{…} 包起来。在 LaTeX 数学模式中,e、i、d 只是普通字母,会排成斜体变量;写成 \mathrm{e}、\mathrm{i}、\mathrm{d} 就成了直立体,与变量 e 或 d 清楚区分。在积分中惯例是加一个细空格,例如 \int_0^1 x^2 \,\mathrm{d}x(标准并不规定空白的量,但为了易读,这种做法几乎通行)。顺带更正一点:你有时会看到 \mathup 这个命令,但它 并非由 isomath 定义。unicode-math 把 \mathup 定义为 \mathrm 的别名,而 kpfonts、mismath 等也各有自己的版本。实测中,在 unicode-math 环境下 \mathrm{d}、\mathup{d}、\symup{d} 三者都输出 U+0064——一个普通的直立 d,只有裸写的 d 得到 U+1D451,即数学斜体的 d。可见 \mathup 是 \mathrm 的同义词,而不是另一种东西。
每次都敲 \mathrm{d} 既麻烦,也一定会在某处漏掉。因此惯常做法是 在导言区一次性定义一个简短命令。写下 \newcommand{\dd}{\mathrm{d}} 之后,正文里只需 \dd x;日后若方针改变,改一行定义整篇文档就会跟着变。反之,把 \mathrm{d} 直接散写在正文各处,等到有人说「还是改回斜体 d 吧」时就无从下手。请把遵守标准这件事,理解成 给约定起名字并集中管理。
% define once in the preamble
\newcommand{\dd}{\mathrm{d}} % upright differential operator
\newcommand{\eu}{\mathrm{e}} % base of the natural logarithm
\newcommand{\iu}{\mathrm{i}} % imaginary unit
% ...
\[
\eu^{\iu\uppi} + 1 = 0, \qquad
\frac{\dd}{\dd x}\,\eu^{x} = \eu^{x}, \qquad
\int_0^{\infty} \eu^{-x}\,\dd x = 1.
\]\uppi 的陷阱 —— 直立的 π 会带来另一套书体
按标准把圆周率 π 排成直立体,通行做法是 upgreek 宏包的 \uppi,但它有一个容易被忽视的代价:upgreek 默认使用 Euler Roman。宏包内的 \ExecuteOptions{Euler} 正是这么写的;实际上,在 \usepackage{upgreek} 之后排出 $\uppi$ 并用 pdffonts 查看,会看到嵌入了 EURM10——赫尔曼·察普夫设计的 Euler 家族字体。于是一份 Computer Modern 的文档里,偏偏这一个 π 出自另一位设计师之手。若在意这一点,可以写 \usepackage[Symbol]{upgreek},改从 URW Symbol(StandardSymL)取字。孰优孰劣取决于你的正文书体,所以 务必看过输出再决定。
另有一点值得知道:upgreek 只提供 希腊小写字母。\upalpha 到 \upomega 一应俱全,但 \upGamma 并未定义,写出来会得到 ! Undefined control sequence.。这是设计而非疏漏——标准 LaTeX 中大写希腊字母本来就是直立体。另外,若使用 unicode-math,则完全不需要 upgreek:该宏包会自动生成 \uppi 和 \upGamma,作为 \symup{…} 的简写。
大写希腊字母为直立体,是 TeX 的惯例而非 ISO 的规定
标准 LaTeX 把 \Gamma、\Omega 等大写希腊字母排成直立体。这是高德纳定下的 TeX 传统,并非 ISO 80000-2 的要求。按标准的想法,用作变量的大写希腊字母(例如角度 Θ)应当像其他变量一样倾斜,只有像 Γ 函数那样 名称确定的函数 才有资格保持直立。其机制简单得出奇:标准 LaTeX 中 \Gamma 是 \mathchar"7000,即第 0 族——直立的 operators 族。isomath 内部载入的 fixmath(Walter Schmidt 所作)只是把它改成 \mathchar"7100。一个十六进制位的变化,就把大写希腊字母移进了第 1 族,即数学斜体的 letters 族——顺带还让 \mathbf 等数学字母表命令能作用于大写希腊字母。
若不想整包引入 isomath,在 pdfLaTeX 下往往可以通过 数学字体宏包的选项 得到同样效果。newtxmath 提供 slantedGreek 与 uprightGreek;实测中,载入 \usepackage[slantedGreek]{newtxmath} 会把 \Gamma 改成 \mathchar"7100(其默认为 \mathchar"7400)。此外还有面向法式排版的 frenchmath 选项。无论选哪条路,关键都是 在整篇文档中一次性定下大写希腊字母的倾斜与否,中途不变。若同一篇论文里 Θ 时而斜体时而直立,读者会以为那是两个不同的量。
math-style=ISO 究竟改变了什么 —— 实测的字符编码
若在 XeLaTeX 或 LuaLaTeX 上使用 unicode-math,整套书体方针可以由 math-style= 这一个键整体切换。可取值有五个:TeX(默认)、ISO、french、upright、literal。效果可以测量,不必猜测——下表来自在 LuaLaTeX 下排出 $\Gamma\ \alpha\ A\ a\ \partial\ \pi$,再从 PDF 中取出字符并列出其 Unicode 码位。切换到 math-style=ISO 后,可以一眼看出大写希腊字母 Γ 从 U+0393(直立)移到了 U+1D6E4(数学斜体)。这正是标准与 TeX 传统正面相撞的那一点。
| 设置 | 大写希腊 Γ | 小写希腊 α | 偏微分 ∂ | 拉丁小写 a |
|---|---|---|---|---|
math-style=TeX | U+0393 直立 | U+1D6FC 斜体 | U+1D715 斜体 | U+1D44E 斜体 |
math-style=ISO | U+1D6E4 斜体 | U+1D6FC 斜体 | U+1D715 斜体 | U+1D44E 斜体 |
math-style=french | U+0393 直立 | U+03B1 直立 | U+2202 直立 | U+1D44E 斜体 |
math-style=upright | U+0393 直立 | U+03B1 直立 | U+2202 直立 | U+0061 直立 |
从这张表可以读出两件事。其一,即使设为 math-style=ISO,π 仍是斜体(U+1D70B)。标准要求常数 π 为直立体,但 unicode-math 无法判别某个 π 是常数还是变量,所以设为 ISO 之后,上一节的 \uppi(或 \symup{\pi})依然必要。其二,math-style=french 这个取值本身就很有意思——法国的排版惯例把希腊字母大小写都排成直立体,拉丁大写也是直立体。「正确的书体」并非只有一种,而是存在地域传统,宏包以一个取值的形式承认了这一点。粗体另有一个键 bold-style=;在默认值 TeX 下,\symbf{v} 是 粗体直立(U+1D42F)。若要得到标准要求的粗斜体向量,请设置 bold-style=ISO,或使用 \symbfit(U+1D497)。
% compile with xelatex or lualatex
\usepackage{amsmath}
\usepackage[math-style=ISO,bold-style=ISO]{unicode-math}
\setmathfont{STIX Two Math}
% ...
\[
\symup{e}^{\symup{i}\uppi} + 1 = 0, \qquad
\int_0^1 x^2 \,\symup{d}x = \frac{1}{3}, \qquad
\symbfit{v} = \symbfit{A}\,\symbfit{x}.
\]向量用粗斜体,张量用无衬线粗斜体
标准还按量的「类型」规定书体:向量与矩阵的符号用粗斜体,张量的符号用无衬线粗斜体。这里最大的陷阱是,常用的 \mathbf{v} 给出的是 粗体直立,而非标准所要求的粗斜体。省事的办法是 bm 宏包的 \bm{v},它在保持斜体的同时只增加字重。若想更忠实于标准,可用 isomath,它提供 \vectorsym{v}、\matrixsym{A}、\tensorsym{T} 这类 按含义命名的命令。这种命名在实务中很有用——半年后重读源码时,\bm{A} 不会告诉你 A 是矩阵、向量还是单纯的强调,而 \matrixsym{A} 一眼就清楚。
不过 isomath 会悄悄做两件事。其一,它 把 \mathbf 重新定义为粗斜体(OML 编码的 bx/it)。这符合标准,但会改变把 \mathbf 当作「直立粗体」使用的既有稿件的外观,因此中途引入时请通读全文复核。其二,由于内部载入 fixmath,大写希腊字母会变成斜体。还有一点:Computer Modern 没有数学用的无衬线粗斜体,所以使用 \tensorsym 时日志中会出现 Font shape OML/cmbr/bx/it in size <10> not available 这样的 字体替换信息(这是信息,不是错误)。实测中由 cmbright 系列顶替。在大量使用张量的文档里,值得看一眼替换后的书体是否可接受。
\usepackage{isomath} % loads fixmath: capital Greek becomes italic
% NOTE: isomath also redefines \mathbf as bold ITALIC (OML bx/it)
% ...
\[
\vectorsym{v} = \matrixsym{A}\,\vectorsym{x},
\qquad
\tensorsym{T}_{ij}.
\]实务方针 —— 遵守到什么程度,在哪里妥协
要严格遵守标准还是贴近本地习惯,取决于文档的性质。判断依据很清楚:投稿的期刊或企业规范是否要求 ISO/JIS 合规? 若要求,按下面的方针整理即可。若不要求,部分采用也完全合理——比如只引入 \mathrm{d},这在任何领域都能提升可读性。但无论选什么,方针都要在一篇文档内保持统一。同一个符号这一页斜体、下一页直立,最容易让读者困惑。
- 把 e、i、d 变成直立体。 在导言区把
\dd、\eu、\iu定义为\mathrm{…},正文中只写这些简短命令。 - 若要严格处理 π,使用
upgreek的\uppi——但其默认会引入 Euler Roman 的字形,请与[Symbol]选项比较后再定。 - 单位交给 siunitx。 避免手写
\mathrm{…},改用\unit{}与\qty{}{},间距和复合单位天然就符合标准。 - 向量与矩阵用粗斜体。 不用
\mathbf(粗体直立),而用\bm,或符合标准的isomath的\vectorsym/\matrixsym/\tensorsym。 - 函数名、偏微分符号和数字无需处理。
\sin、\cos、\log、\lim、\partial、123本来就满足标准。要添加自己的函数名时,用amsmath的\DeclareMathOperator{\rank}{rank}即可得到同样的直立体与间距。 - 大写希腊字母一次定好,不再更改。 要让它倾斜,可用
isomath(经由fixmath)、newtxmath的slantedGreek,或math-style=ISO。
最后谈一句 physics 宏包。它能轻松给出直立的微分 \dd 和导数 \dv,看起来很吸引人,但其命令名与其他宏包冲突已是众所周知。实测中同时载入 physics 与 siunitx,两者争夺 \qty 的定义,产生了 ! Missing $ inserted. 和 ! Extra }, or forgotten $.(存在用于修补的 physics-patch,近年也常使用 derivative 等替代方案)。这件事在 physics 专页中有详细叙述。单位本身则是 siunitx 那一页的主题,若需要复合单位或有效数字,请前往那里。意识到书体的 含义 并始终一致地应用它——归根结底,合规的本质就在于此。