1. 为什么要在 Markdown 里折腾数学符号
如果你平时写技术笔记、论文草稿或者博客,肯定遇到过这种尴尬:想写个简单的分数或者求和公式,结果只能用纯文本硬凑,比如(a+b)/c或者sum(x_i),读起来费劲,排版也丑。Markdown 本身是轻量级标记语言,设计初衷是让写作者专注内容而不是格式,所以它原生并不支持复杂的数学公式。但搞技术的人哪能离得开公式?从简单的上下标到复杂的矩阵、积分,总得有个办法在 Markdown 里优雅地写出来。
这就是 LaTeX 出场的时候了。LaTeX 是一套专业的排版系统,尤其擅长数学公式排版,它的语法精确、表现力强,几乎成了学术写作的事实标准。现在主流的 Markdown 编辑器和渲染引擎(比如 Typora、Obsidian、VS Code 配合插件、Jupyter Notebook、GitHub 的 README 渲染等)都支持嵌入 LaTeX 语法来渲染数学公式。你只需要用$符号把公式包起来,就能在 Markdown 文档里得到漂亮的数学排版。
这篇文章就是写给那些需要在 Markdown 里写数学公式的人——不管你是学生、科研人员、工程师,还是偶尔要写点技术文档的开发者。我会从最基础的语法讲起,一步步拆解常见符号的写法、排版技巧、踩过的坑,以及在不同平台上的兼容性处理。看完你就能在自己的 Markdown 文档里自如地插入数学公式,不用再截图或者贴图片了。
2. 核心语法与渲染原理拆解
2.1 行内公式与块级公式的区别
在 Markdown 里写 LaTeX 数学公式,首先要搞清楚两种模式:行内公式(inline)和块级公式(display)。行内公式是嵌在文字段落里的,比如“当 $x > 0$ 时,函数单调递增”,这里的$x > 0$就是行内公式。块级公式则是独立成行的,通常居中显示,适合比较长或者重要的公式。
行内公式用单个美元符号$...$包裹,块级公式用双美元符号$$...$$包裹。这个规则在大多数渲染引擎里是通用的,但也有一些变体,比如有的平台用\(...\)表示行内,用\[...\]表示块级。我个人的习惯是统一用美元符号,因为输入快、可读性好,而且兼容性最广。
注意:如果你的文档里本身就要显示美元符号(比如写价格),记得用反斜杠转义:
\$,否则渲染引擎会把它当成公式的开始。
块级公式还有一个好处是可以带编号,方便在文中引用。比如:
$$ E = mc^2 \tag{1} $$渲染出来就是带编号 (1) 的公式。不过编号功能在不同平台上的支持程度不一样,有的需要额外配置,这个后面会细说。
2.2 渲染引擎的工作流程
你可能好奇,Markdown 是怎么把$\frac{a}{b}$变成漂亮的分数形式的?这背后其实有一套完整的处理链路。Markdown 解析器首先会把文档解析成 HTML 结构,然后数学公式的渲染通常交给专门的库来处理,比如KaTeX或MathJax。
KaTeX 的特点是渲染速度快、输出的是纯 HTML 和 CSS,不依赖 JavaScript 运行时,所以适合对性能要求高的场景。MathJax 功能更全,支持更多的 LaTeX 命令和扩展,但渲染速度相对慢一些,因为它需要加载较大的 JavaScript 文件。GitHub 的 README 渲染用的是 MathJax 的简化版,而 Typora、Obsidian 这些编辑器大多内置了 KaTeX。
这个区别对你来说意味着什么?如果你写的公式用了一些冷门的 LaTeX 命令,在 KaTeX 里可能渲染不出来,但在 MathJax 里没问题。反过来,KaTeX 对语法的要求更严格,写错了会直接报错而不是默默忽略。所以如果你发现某个公式在本地编辑器里显示正常,推到 GitHub 上却挂了,大概率就是渲染引擎的兼容性问题。
2.3 常用符号的分类与记忆方法
LaTeX 的数学符号命令有几百个,但真正常用的也就几十个。我习惯把它们分成几类来记:
- 希腊字母:小写用
\alpha、\beta、\gamma,大写首字母大写即可,比如\Gamma、\Delta。注意有些大写字母长得和英文字母一样,比如\Alpha其实就是 A,所以 LaTeX 没有定义这些命令。 - 上下标:下标用
_,上标用^。如果上下标多于一个字符,要用花括号包起来,比如x_{ij}而不是x_ij。 - 分数与根号:分数用
\frac{分子}{分母},根号用\sqrt{被开方数},n 次根号用\sqrt[n]{...}。 - 求和与积分:求和
\sum_{i=1}^{n},积分\int_{a}^{b},多重积分\iint、\iiint。 - 关系运算符:小于等于
\leq,大于等于\geq,不等于\neq,约等于\approx。 - 箭头:右箭头
\rightarrow,左箭头\leftarrow,双向\leftrightarrow,长箭头\longrightarrow。 - 集合符号:属于
\in,不属于\notin,包含\subset,并集\cup,交集\cap。
这些命令不需要死记硬背,用多了自然就熟了。我建议你建一个自己的“公式速查表”文档,遇到新的就记下来,下次直接复制粘贴。
3. 高频公式场景与实操写法
3.1 分数、指数与对数的排版细节
分数大概是除了上下标之外最常用的数学结构了。\frac{a}{b}是最基本的写法,但在行内模式下,分数会被压缩得很小,看起来比较挤。比如$\frac{1}{2}$渲染出来就是 ½ 的样子,虽然能看,但不够美观。如果分数比较复杂,建议用块级公式,或者用\dfrac强制显示为展示样式(display style),这样分子分母会正常大小显示。
指数和对数的写法相对简单:e^{x}表示 e 的 x 次方,\ln(x)表示自然对数,\log_{2}(n)表示以 2 为底的对数。注意\ln、\log、\sin、\cos这些函数名要用反斜杠开头,这样渲染出来是正体,而不是斜体变量。如果你直接写ln(x),渲染出来会是 l 乘以 n 乘以 (x),意思完全变了。
实操心得:写指数的时候,如果指数部分有多个字符,一定要用花括号包起来。
e^xy会被渲染成 e 的 x 次方再乘以 y,而e^{xy}才是 e 的 xy 次方。这个坑我踩过不止一次。
3.2 求和、积分与极限的上下限控制
求和符号\sum和积分符号\int在行内模式下,上下限会写在符号的右侧,比如$\sum_{i=1}^{n} i$渲染出来是 Σ 右边跟着 i=1 到 n。但在块级模式下,上下限会写在符号的正上方和正下方,看起来更专业。
如果你希望在行内模式下也强制上下限在正上方,可以用\limits命令:$\sum\limits_{i=1}^{n} i$。不过这样会让行高变大,影响段落排版,所以一般只在特别需要强调的时候用。
积分符号的上下限写法类似:\int_{0}^{\infty} f(x) dx。注意微分符号dx里的 d 通常用正体,所以写成\mathrm{d}x更规范。不过很多期刊和平台不强制要求,看你的目标场景。
极限符号\lim的写法是\lim_{x \to 0},其中\to是箭头。如果是趋向于无穷,用\infty。
3.3 矩阵、方程组与多行公式的对齐
矩阵和方程组是 LaTeX 排版里比较复杂的部分,但掌握了规律也不难。矩阵用\begin{matrix}...\end{matrix}环境,行内用&分隔列,用\\换行。比如:
$$ \begin{pmatrix} a & b \\ c & d \end{pmatrix} $$pmatrix是带圆括号的矩阵,bmatrix是带方括号的,vmatrix是带竖线的(行列式)。如果你需要省略号,用\cdots(横向)、\vdots(纵向)、\ddots(对角线)。
方程组用\begin{cases}...\end{cases},比如:
$$ \begin{cases} x + y = 1 \\ 2x - y = 3 \end{cases} $$多行公式对齐用\begin{align}...\end{align},在需要对齐的位置放&,比如等号对齐:
$$ \begin{align} f(x) &= x^2 + 2x + 1 \\ &= (x + 1)^2 \end{align} $$注意:
align环境在部分 Markdown 渲染器里需要额外的包支持,如果渲染不出来,可以退而求其次用\begin{array}手动控制对齐。
3.4 希腊字母与特殊符号的输入技巧
希腊字母的输入其实有规律可循:大部分小写希腊字母的英文拼写就是命令名,比如\alpha、\beta、\gamma、\delta、\epsilon、\theta、\lambda、\mu、\pi、\sigma、\phi、\omega。大写的话首字母大写,比如\Gamma、\Delta、\Theta、\Lambda、\Pi、\Sigma、\Phi、\Omega。
有几个容易混淆的:\epsilon和\varepsilon是两种不同形态的 epsilon,前者是 lunate 形,后者是花体形。\phi和\varphi也是类似的情况。一般来说,\varepsilon和\varphi在学术论文里更常见。
特殊符号里,无穷大\infty、偏微分\partial、梯度\nabla、空集\emptyset、实数集\mathbb{R}、自然数集\mathbb{N}这些都很常用。\mathbb是黑板粗体,需要amssymb包支持,大部分渲染器都内置了。
4. 跨平台兼容性与避坑指南
4.1 不同 Markdown 编辑器的支持差异
这是最让人头疼的部分。同样一段公式,在 Typora 里显示完美,复制到 GitHub 上就变成了一堆乱码。我整理了一个常见平台的兼容性对照表:
| 平台/编辑器 | 渲染引擎 | 行内公式 | 块级公式 | 矩阵环境 | 编号引用 |
|---|---|---|---|---|---|
| Typora | KaTeX | 支持 | 支持 | 支持 | 部分支持 |
| Obsidian | MathJax | 支持 | 支持 | 支持 | 支持 |
| VS Code (Markdown Preview Enhanced) | KaTeX/MathJax | 支持 | 支持 | 支持 | 支持 |
| GitHub README | MathJax 简化版 | 支持 | 支持 | 部分支持 | 不支持 |
| Jupyter Notebook | MathJax | 支持 | 支持 | 支持 | 支持 |
| 语雀 | KaTeX | 支持 | 支持 | 支持 | 不支持 |
| Notion | KaTeX | 支持 | 支持 | 部分支持 | 不支持 |
从表里可以看出,KaTeX 和 MathJax 是两大主流。KaTeX 渲染快但支持的命令少一些,MathJax 功能全但慢。如果你写的公式要在多个平台发布,建议尽量用最基础的 LaTeX 命令,避免冷门语法。
4.2 常见渲染失败原因与排查步骤
公式渲染不出来,通常有以下几个原因:
- 美元符号冲突:文档里有多处
$,渲染器可能把不该配对的地方配对了。解决方法是检查所有$是否成对出现,必要时用\$转义。 - 反斜杠转义问题:在某些 Markdown 解析器里,反斜杠本身需要转义,所以
\\才能表示一个反斜杠。如果你发现\frac变成了frac,就是这个问题。 - 环境不支持:
align、cases这些环境在部分渲染器里需要额外配置。可以先用array替代测试。 - 特殊字符未转义:下划线
_在 Markdown 里是斜体标记,在公式里如果出现在不该出现的地方,可能会被解析成斜体。虽然公式内部的_通常会被正确识别,但边界情况还是要注意。 - 缓存问题:有时候改了公式但预览没更新,强制刷新或者重启编辑器试试。
实操心得:我习惯在文档开头加一个测试公式,比如
$a^2 + b^2 = c^2$,如果这个都渲染不出来,说明整个文档的公式支持有问题,不用一个个去查。
4.3 公式编号与引用的实用方案
如果你写的是学术文档,公式编号和引用是刚需。但 Markdown 原生不支持交叉引用,所以需要一些技巧。
最简单的方案是手动编号:在公式末尾用\tag{1}加上编号,然后在文中用纯文本写“见公式 (1)”。缺点是编号要手动维护,插入新公式后后面的编号全要改。
进阶方案是用 HTML 锚点:给公式加一个id,然后用链接引用。比如:
$$ E = mc^2 \tag{1} $$然后在文中写[见公式 (1)](#eq1),不过这个方案需要渲染器支持 HTML 锚点,而且\tag和锚点的结合在不同平台上表现不一致。
最省心的方案是用支持交叉引用的工具链,比如 Pandoc 配合 LaTeX 输出 PDF,或者用 Quarto 写文档。但如果只是写博客或笔记,手动编号其实够用了,毕竟公式数量不会太多。
5. 进阶技巧与效率提升
5.1 自定义命令与宏定义
如果你经常写某个复杂的表达式,可以在文档开头用\newcommand定义宏。比如:
$$ \newcommand{\R}{\mathbb{R}} \newcommand{\norm}[1]{\left\| #1 \right\|} $$之后就可以用\R表示实数集,用\norm{x}表示范数。这样不仅输入快,而且公式更简洁易读。
不过要注意,\newcommand在不同渲染器里的支持程度不一样。KaTeX 支持大部分宏定义,但有些平台会出于安全考虑禁用这个功能。如果你的公式要发布到公共平台,建议还是老老实实写完整命令。
5.2 公式排版的美化细节
同样的公式,排版细节不同,专业感差很多。几个我常用的技巧:
- 自动调整括号大小:用
\left(和\right)代替普通的(和),这样括号会根据内容高度自动缩放。比如\left( \frac{a}{b} \right)的括号会比( \frac{a}{b} )大一圈,看起来更协调。 - 多行公式的间距控制:在
align环境里,可以用\\[10pt]手动增加行间距,避免公式太挤。 - 条件表达式的对齐:用
cases环境时,条件部分通常用& \text{if } x > 0的写法,\text里的内容会以正体显示,不会变成斜体变量。 - 单位符号的正体:物理量单位比如
\text{m/s}、\text{kg}要用\text或\mathrm包起来,否则会变成斜体,不符合规范。
5.3 从图片公式到文本公式的迁移策略
如果你之前习惯用截图插入公式,现在想转成 LaTeX 文本公式,工作量可能不小。我的建议是分步走:先把最常用的公式转过来,比如文档里的核心公式;然后逐步替换次要的。转换的时候可以用一些辅助工具,比如手写识别或者公式 OCR,但准确率参差不齐,最终还是得手动校对。
另一个策略是新建文档直接用 LaTeX 写,旧文档保持原样。这样不用一次性全部迁移,新文档还能享受文本公式的好处——可搜索、可编辑、体积小、缩放不失真。
注意:截图公式在深色模式下往往显示效果很差,而 LaTeX 公式会自动适配主题颜色,这也是迁移的一个理由。
6. 我踩过的坑与实战建议
6.1 那些年我写错的公式语法
刚开始用 LaTeX 写公式的时候,我犯过不少低级错误。比如把\frac{1}{2}写成\frac(1)(2),把\sqrt{x}写成\sqrt(x),结果渲染出来完全不是那么回事。LaTeX 的语法是花括号{}表示分组,圆括号()只是普通字符,这个区别一定要记牢。
还有一次写矩阵,忘了写\end{matrix},结果整个文档后面的内容都被吞进公式里了,渲染出来一片混乱。所以写环境的时候,一定要成对写\begin和\end,最好先写好框架再填内容。
另一个常见的坑是下标里的逗号。比如x_{i,j}渲染出来是 x 下标 i,j,但如果你写成x_i,j,渲染出来是 x 下标 i 然后逗号 j,意思完全不同。多字符下标一定要用花括号包起来。
6.2 公式太多导致渲染卡顿怎么办
如果你在一个文档里写了几百个公式,尤其是用 MathJax 渲染的,页面可能会变得很卡。我遇到过一篇笔记加载了十几秒才渲染完,体验极差。
解决办法有几个:一是尽量用 KaTeX 代替 MathJax,渲染速度快很多;二是把长文档拆成多个短文档,每个文档的公式数量控制在合理范围内;三是对于特别复杂的公式,考虑用图片代替,虽然失去了文本公式的优势,但至少不会卡顿。
还有一个技巧是延迟渲染:有些编辑器支持只渲染可视区域的公式,滚动到哪里渲染到哪里。这个功能在 Obsidian 里可以通过插件实现,Typora 则默认就是即时渲染,体验很好。
6.3 团队协作中的公式规范建议
如果你和团队一起写文档,公式风格不统一会很乱。我们团队的做法是定一个简单的规范:行内公式统一用$...$,块级公式统一用$$...$$,变量用斜体,函数名用正体,单位用\text{}包裹。虽然不是什么硬性标准,但至少看起来整齐。
另外,提交文档之前最好在目标平台上预览一遍,确认公式都能正常渲染。我们有一次把文档推到 GitHub 上,结果发现所有align环境都不支持,只好连夜改成array。从那以后,我们就在 CI 流程里加了一步公式渲染检查,提前发现问题。
实操心得:如果你的团队用 Git 管理文档,可以在
.gitattributes里把 Markdown 文件标记为文本文件,避免 Git 自动转换换行符导致公式里的\\被破坏。
6.4 常用公式速查表
最后附上我整理的一份速查表,覆盖了日常写作中 90% 的场景:
| 场景 | LaTeX 写法 | 渲染效果 |
|---|---|---|
| 分数 | \frac{a}{b} | a/b 上下结构 |
| 上标 | x^{2} | x² |
| 下标 | x_{i} | xᵢ |
| 求和 | \sum_{i=1}^{n} | Σ 上下限 |
| 积分 | \int_{0}^{1} | ∫ 上下限 |
| 极限 | \lim_{x \to 0} | lim 下方 x→0 |
| 根号 | \sqrt{x} | √x |
| 矩阵 | \begin{pmatrix} a & b \\ c & d \end{pmatrix} | 2x2 矩阵 |
| 方程组 | \begin{cases} ... \end{cases} | 大括号方程组 |
| 希腊字母 | \alpha \beta \gamma | α β γ |
| 无穷 | \infty | ∞ |
| 偏导 | \frac{\partial f}{\partial x} | ∂f/∂x |
| 向量 | \vec{v} | v 带箭头 |
| 点乘 | \cdot | · |
| 叉乘 | \times | × |
这份表我打印出来贴在显示器旁边,写公式的时候随时瞄一眼,省得每次都去搜。
写数学公式这件事,说到底就是个熟练度的问题。刚开始可能觉得语法繁琐,但写多了就变成肌肉记忆了。我现在的状态是,想到什么公式直接就能敲出来,比打开公式编辑器快得多。而且文本公式的好处是,你可以用 Git 管理、可以 diff、可以搜索,这些都是图片公式做不到的。如果你还在用截图写公式,真的建议花一个下午把常用语法过一遍,后面省下的时间绝对值得。