「齐次」这个词在方程课里见过:各项次数相同的式子叫齐次式。把它请到坐标上,就是本节的主角齐次坐标——一项让"有限点"与"无穷远点"领到同一种身份证的发明。2.1 节给出了"每方向补一点"的直觉方案,本节把它升级为纯代数构造:先造空间,再验证它正是我们想要的那个手术结果。
射影空间:Pⁿ(k) 定义为 (kⁿ⁺¹ 去掉原点) 除以"非零倍数视为相同"的等价关系。向量 (x₀,…,xₙ) 与 (λx₀,…,λxₙ)(λ≠0)代表同一个点,记作 (x₀ : … : xₙ),这组数称为齐次坐标。齐次坐标没有唯一代表元,只有比例。
定义只有两行,拆开看每行都在干活。"去掉原点"是因为原点没有方向,它不该代表任何点。"按比例打包"则精确实现了 2.1 节的需求:三维空间里过原点的每条直线(即每个方向)被压缩成一点。拿 P² 检验:
第三坐标非零的向量,打包成仿射平面上的普通点(取 (x/z, y/z) 还原);第三坐标为零的向量,打包成无穷远点。一套坐标同时容纳有限与无穷,这就是齐次坐标的全部野心。

齐次坐标里,方程也必须齐次。P² 中直线的方程形如
aX + bY + cZ = 0
验证两件事。其一,若 (X:Y:Z) 满足方程,(λX:λY:λZ) 也满足——线性齐次式在倍数变换下只差一个因子 λ,零点性质不变,所以"点满足方程"是良定义的。其二,无穷远直线是 Z = 0:齐次坐标第三位为零的点全在它上面,一步到位。
仿射直线 y = 0 齐次化后是 Y = 0,它的无穷远点解 Y=0 且 Z=0,得 (1 : 0 : 0);仿射直线 x = 0 齐次化得 X = 0,无穷远点 (0 : 1 : 0)。两条"平行"直线 Y=0 与 Y−Z=0 联立:Z=0 进来后两式合一,交点正是 (1:0:0)——2.1 节的账目在方程层面自动结清,**不需要任何特殊规则,齐次性自己把无穷远算出来了**。
再看曲线。圆 x² + y² = 1 齐次化为 X² + Y² = Z²(二次齐次),尖点 y² = x³ 齐次化为 Y²Z = X³(三次齐次)。一般规则一句话:每一项补到同一总次数,缺的次数用 Z 补齐——这正是"齐次"二字的操作含义,2.3 节把它写成正式算法。
射影直线 P¹ 由 (x₀ : x₁) 组成,相当于给每条仿射直线补上自己的无穷远点。它有个著名的身份:复数域上,P¹(ℂ) 与黎曼球面(扩充复平面)完全一致——扩平面 ℂ ∪ {∞} 的 ∞ 就是 (1:0)。复分析里"极点处函数值取无穷"的别扭说法,在 P¹ 里变成"函数正经取值于一个普通点"。第 3 章谈态射时,P¹ 会是出镜率最高的试验田。
P¹ 还有个"数得过来"的趣味案例:换成只有五个元素的有限域 F₅ 时,P¹(F₅) 的点是 (1 : a)(a 取五种值)加 (0 : 1),共六个点——五张有限点的票加一张无穷远的票,"n+1 个点"的公式在有限域照样成立。这个玩具案例并非闲笔:6.4 节把椭圆曲线搬进有限域做密码学,数的正是这类"有限点集";那时 P¹ 的 n+1 个点会变成椭圆曲线点数的对照组(一条曲线在 F₅ 上的点数大约是 6 上下浮动,浮动幅度有精确的界——哈塞界)。射影空间不挑域:实数、复数、有限域通吃,这是它作为"舞台"的职业素养。
齐次坐标的读写还有两条公约要立好。公约一:代表元自己挑,但挑了要认账——写 (1 : 2 : 1) 还是 (3 : 6 : 3) 全凭场合方便,可一旦进入等式(比如"点满足方程 F=0"),必须先声明用的哪个代表元,因为 F(1,2,1) 与 F(3,6,3) 数值不同,为零的性质才相同。公约二:卡片优先。处理具体问题时先把"第三坐标非零"的卡抽出来(Z≠0 卡),在卡里用熟悉的仿射坐标 (x, y) = (X/Z, Y/Z) 干活,无穷远相关的问题再回射影坐标——本册后面每章的"无穷远点计算"环节,用的都是这套"卡片干活、射影判案"的双轨流程。
写代码处理射影点时,核心是"选代表元"与"还原仿射坐标"两个动作。下面是概念代码:
def homogenize(x, y): """仿射坐标 -> 齐次坐标(仿射部分)""" return (x, y, 1.0) def dehomogenize(p): """齐次坐标 -> 仿射坐标;第三位为零则返回无穷远标记""" X, Y, Z = p if Z == 0: return ('point at infinity', (X, Y)) return (X / Z, Y / Z) def same_point(p, q): """判断两个齐次坐标是否同一个点:交叉相乘""" X1, Y1, Z1 = p X2, Y2, Z2 = q return (X1*Y2 - X2*Y1 == 0 and Y1*Z2 - Y2*Z1 == 0) print(dehomogenize((2, 4, 2))) # (1.0, 2.0) print(dehomogenize((1, 0, 0))) # 无穷远点,方向 (1, 0) print(same_point((1, 2, 1), (3, 6, 3))) # True
注意 same_point 里用的是交叉相乘而不是除法:齐次坐标的等价检验天然写成乘法等式,一来避开"选哪个代表元"的麻烦,二来在只有整数或有限域的环境里照样能跑。有限域上的椭圆曲线密码(6.4 节)处理 P² 点时用的正是这类乘法等式。
三个易错点。其一,(0:0:0) 不是任何点:去掉原点是定义的一部分,遇到它先查自己的齐次化是否漏了 Z。其二,齐次坐标之间不能比大小、不能加:两个点坐标相加得到的是"两向量之和的方向",没有任何几何含义。其三,"P² 比 A² 多一条直线"这句话要小心:多的是一条射影直线(无穷远直线),它自身也是一条正经的曲线,第 4 章数交点时它与其他曲线照样按贝祖记账。
本节在知识体系里的位置:射影空间正式建成,第 1 章的字典可以在新舞台上原样开场(V(F) 对齐次 F 照样定义)。下一节给齐次化立算法、算闭包,把圆、双曲线、尖点的无穷远点一次结清。