如果你的首页刷到过《【全网首个】尺规作图正65537边形完整过程manim动画!尺规作图的癫疯!》这种标题,大概会有两种反应:一种是觉得“标题党又来骗点击了”,另一种是好奇“正65537边形到底有没有可能用尺规画出来”。
答案是:理论上可以,工程上极其离谱,视觉上约等于一个圆。这篇文章我就从数学原理、尺规作图的判定依据、到一个完整可运行的 Manim 动画工程,把正 65537 边形这件事彻底拆开讲清楚。即使你完全没接触过 Manim,只要会一点 Python,也能在本地跑出属于你自己的“尺规作图极限挑战”动画。
本文会覆盖:费马素数和高斯判据、为什么正 65537 边形可以通过尺规作图构造、Manim 环境搭建、从正 3 边形到正 65537 边形的动画对比、顶点坐标级的高阶多边形绘制,以及渲染大数据量几何对象时的性能优化建议。
1. 一个“画不出来”的多边形,为什么值得研究
1.1 正65537边形的特殊性
先区分两个概念。我们现在讨论的“尺规作图”,默认只允许两种工具:没有刻度的直尺和圆规。用这两种工具,能不能作出一个正 n 边形,不是你想当然画一个“近似圆”就可以了,而是要求所有的顶点在逻辑上都必须是精确可构造的。
正三角形、正方形、正五边形很早就被人画出来了。正七边形反而是古希腊几何学家一直卡住的问题。为什么数字一变大,难度反而不按常理变化?因为一个正 n 边形能不能用尺规作图,取决于 n 的数学结构,而不是取决于边数多少。
正 65537 边形之所以特殊,是因为 65537 本身是 2 的 16 次方加 1,也就是:
65537 = 2^16 + 1
同时 65537 是一个素数。像这种形如 2^(2^k) + 1 的数,叫做费马数。目前人类确认的费马素数只有前 5 个,分别是 3、5、17、257 和 65537。第 6 个费马数 2^32 + 1 已经是合数,后面目前也没有发现新的费马素数。
这个“恰好是费马素数”的属性,让正 65537 边形成为数学上允许尺规作图的边数之一。
1.2 高斯定理与可作图判据
高斯在 19 岁左右证明了这样一个非常漂亮的结论:一个正 n 边形可以尺规作图,当且仅当 n 可以写成:
n = 2^k × p1 × p2 × … × pr
其中 p1、p2、…、pr 是互不相同的费马素数,k 是非负整数。
这个结论为什么成立?简单理解:尺规作图能处理的本质操作是“解二次方程”。一个复数单位根能不能用尺规构造,取决于它所在的数域中的扩张次数是否是 2 的幂。对于正 n 边形,需要构造 n 次单位根,而 n 次单位根所在的数域扩张次数等于欧拉函数 φ(n)。只有当 φ(n) 是 2 的幂时,才能通过有限次开平方操作构造出来。
对于 n = 65537:
φ(65537) = 65536 = 2^16
正好是 2 的幂。因此正 65537 边形在原理上完全可以用尺规作图构造出来。
1.3 为什么说它是尺规作图的“癫疯”
既然数学上可行,那实际操作呢?这里才是“癫疯”的地方。高斯虽然给出了正 17 边形的尺规作图方法,但对于正 65537 边形,真正给出完整作图方案的人是德国数学家赫尔梅斯(Johann Gustav Hermes)。他花了大概 10 年时间,整理出一套理论上可行的作图步骤,最终的手稿超过 200 页,至今还保存在哥廷根大学图书馆。
注意,这只是“作图方案”,不是真的在纸上画出来一个肉眼可辨认的 65537 边形。因为按照这套方案执行,步骤数量会是天文数字,实际物理作图根本不可能完成。更直观地说,如果一个正 65537 边形的外接圆半径是 1 米,那么它的每条边大约只有 0.096 毫米,肉眼很难分辨每个顶点在哪里。整个图形看起来就是一个完美圆形。
所以这个项目标题说的“完整过程”,准确理解应该是“完整描述构造原理和视觉呈现”,而不是真的播放出几百万步圆规直尺操作。
2. 数学准备:从费马素数到高斯判据
2.1 费马数序列
费马数的一般形式是:
F_k = 2^(2^k) + 1
前几项为:
- F0 = 3
- F1 = 5
- F2 = 17
- F3 = 257
- F4 = 65537
其中前 5 项都是素数。F5 = 4294967297 = 641 × 6700417,不是素数。所以目前已知的费马素数只有 5 个。
这些数之所以在尺规作图问题里有特殊地位,是因为高斯判据中“互不相同的费马素数”这一条件。正 15 边形可以作图,因为 15 = 3 × 5;正 51 边形可以作图,因为 51 = 3 × 17;正 65537 边形可以作图,因为 65537 本身就是一个费马素数。
2.2 高斯判据的使用方法
实际判断一个正 n 边形是否可以尺规作图,不需要真的去数因数。可以直接计算欧拉函数 φ(n),然后检查 φ(n) 是否是 2 的幂。
例如:
- n = 7:φ(7) = 6,不是 2 的幂,所以正七边形不能尺规作图。
- n = 17:φ(17) = 16 = 2^4,可以。
- n = 257:φ(257) = 256 = 2^8,可以。
- n = 65537:φ(65537) = 65536 = 2^16,可以。
当然,这个判据是“存在构造方案”,不是真的推荐你去画。在动画中我们真正能做的,是把这些多边形尽可能多地绘制出来,去感受不同边数带来的视觉变化。
2.3 单位根视角的补充理解
从复数角度看,正 n 边形就是把单位圆上的 n 等分点依次连接起来。这些等分点对应的复数是方程:
x^n − 1 = 0
的根,也就是:
e^(2πik/n),其中 k = 0, 1, 2, …, n − 1
当 n 是费马素数时,n 次单位根所在的分圆域恰好是 2 的幂次扩张。因此只需要逐层解二次方程,就能把这些根表示成有限次加减乘除和开平方的表达式。这也是高斯判据的底层逻辑。
以后你在别的资料里看到“正 257 边形由某位数学家作出”,提到“分圆多项式”“二次扩张”,本质都是这一套思路。
2.4 实际作图的规模
以正 65537 边形为例,如果外接圆半径为 r,中心角是:
θ = 2π / 65537 ≈ 0.0000959 弧度
转化为度数约 0.00549 度。如果半径是 1 单位,边长大约是:
2 × sin(θ/2) ≈ 0.0000959
假设你在一个半径 400 像素的圆上画 65537 个顶点,每个相邻顶点的像素距离大约为:
400 × 0.0000959 ≈ 0.0384 像素
也就是说,在标准分辨率下,顶点间距小于一个像素。这就是为什么任何渲染工具画出来的正 65537 边形,视觉上都只能是一个圆。
3. Manim 环境准备与项目组织
如果你已经熟悉 Manim,可以直接跳到第 4 节。如果不熟悉,下面这套环境搭建步骤足够帮你把动画跑起来。
3.1 安装 Manim
本文使用的是 Manim 社区版,也就是 GitHub 上 3b1b 官方项目衍生出来的社区维护版本。安装命令:
pip install manim如果你使用虚拟环境:
python -m venv venv source venv/bin/activate # Windows 下是 venv\Scripts\activate pip install manim安装完成后,可以查看版本信息:
manim --version3.2 依赖项说明
Manim 渲染需要以下几个外部程序:
| 依赖 | 作用 | 说明 |
|---|---|---|
| Python 3.8+ | 运行环境 | Manim 依赖 Python 3.8 及以上版本 |
| FFmpeg | 视频编码 | 不安装会无法导出 mp4 |
| LaTeX(可选) | 渲染数学公式 | 不带 LaTeX 也能用部分文本,但 MathTex 依赖它 |
| Cairo / Pango | 字体和图形渲染 | pip 安装 manim 时会自动处理 |
FFmpeg 的安装方式根据操作系统有所不同。macOS 可以用:
brew install ffmpegUbuntu 可以用:
sudo apt install ffmpegWindows 用户建议从 FFmpeg 官网下载编译好的二进制文件,并把 bin 目录添加到系统 PATH。
如果暂时不想装 LaTeX,可以先用Text()和MathTex()之外的基础图形。但要显示数学公式,还是建议安装 TeX 发行版。macOS 推荐 MacTeX,Ubuntu 推荐 texlive-latex-extra,Windows 推荐 TeX Live。
3.3 项目文件结构
本文示例项目结构如下:
fermat-polygon/ ├── scenes/ │ ├── __init__.py │ ├── basic_polygons.py │ ├── hex65537.py │ └── compass_demo.py ├── media/ │ ├── videos/ │ └── images/ ├── requirements.txt └── README.md实际演示时,为了简单,可以直接把多个 Scene 类写在一个.py文件里,用 Manim 命令行参数选择要渲染的类。下面统一使用这种单文件组织方式。
4. 用 Manim 绘制正多边形
4.1 最简单的正多边形动画
先写一个最小可运行示例:
# 文件路径:basic_polygons.py from manim import * class PentagonDemo(Scene): def construct(self): polygon = RegularPolygon(5, radius=2, color=BLUE) self.play(Create(polygon)) self.wait()这段代码创建了一个正五边形,并使用Create动画把它绘制出来。RegularPolygon是 Manim 内置的多边形类,第一个参数是边数,第二个参数是外接圆半径。
运行命令:
manim -pql basic_polygons.py PentagonDemo其中-p表示渲染完成后预览,-ql表示低画质。低画质渲染速度更快,开发调试时够用。如果要输出高清:
manim -qh basic_polygons.py PentagonDemo4.2 对比正3、正5、正17、正257的多边形
为了直观感受不同边数的差异,我们可以把正三角形、正五边形、正十七边形、正二百五十七边形放到同一个场景里对比:
from manim import * class PolygonComparison(Scene): def construct(self): captions = [("正三角形", 3), ("正五边形", 5), ("正十七边形", 17), ("正二百五十七边形", 257)] for i, (text, n) in enumerate(captions): polygon = RegularPolygon(n, radius=2) label = Text(text, font_size=36).next_to(polygon, DOWN) self.play(Create(polygon), FadeIn(label)) self.wait(1) if i < len(captions) - 1: self.play(FadeOut(polygon), FadeOut(label))运行:
manim -pql basic_polygons.py PolygonComparison注意,当 n 等于 257 时,RegularPolygon生成的图形在视觉上已经非常接近圆。这是正常的,因为在 400 像素级别的分辨率里,257 条边的折线和圆的差距已经很小。
从这里就能推想,真正的 65537 边形在高清视频里看起来必然是一个圆。
4.3 运行结果说明
渲染完成后,默认输出目录是media/videos/basic_polygons/。文件名类似:
PolygonComparison-480p15.mp4480p15表示低画质 480p、15 帧每秒。如果使用-qh,会生成比较清晰的 1080p 视频。
5. 进阶实战:绘制正65537边形
5.1 用顶点坐标构造 Polygon
由于RegularPolygon在边数非常大时可能不是最优路线,我们可以直接用数学方式计算所有顶点坐标,再用Polygon创建对象。
# 文件路径:hex65537.py from manim import * import numpy as np class Hex65537Visual(Scene): def construct(self): n = 65537 radius = 3.0 vertices = [ np.array([ radius * np.cos(TAU * i / n), radius * np.sin(TAU * i / n), 0 ]) for i in range(n) ] polygon = Polygon(*vertices, color=BLUE) # 直接 add,避免 Create 在 65537 条边上做逐段动画 self.add(polygon) self.wait()这段代码的核心是:
TAU是 Manim 内置常量,等于 2π。- 对 i = 0 到 65536,依次计算顶点在单位圆上的坐标。
- 将这 65537 个顶点传入
Polygon。 - 使用
self.add()直接显示,而不是self.play(Create(polygon))。
运行:
manim -pql hex65537.py Hex65537Visual5.2 为什么建议用 add 而不是 Create
Create的作用是让一个 VMobject 从“没有”到“完整”动态显示。对于 3 条边、5 条边的多边形,这个动态效果非常漂亮。但是对于 65537 条边,Create会在每一帧里不断更新大量的路径,导致计算量爆炸,甚至可能出现渲染一个几十秒动画需要几个小时的情况。
如果只是想展示正 65537 边形的视觉形态,直接self.add(polygon)然后self.wait()就足够了。这样视频里一开始就是完整的“圆”,不会因为逐帧绘制而卡死。
5.3 让画面更直观:增加文字说明
为了让观众明白“这是一个正 65537 边形”,可以在画面中同时显示相关公式:
class Hex65537WithText(Scene): def construct(self): n = 65537 radius = 2.8 vertices = [ np.array([ radius * np.cos(TAU * i / n), radius * np.sin(TAU * i / n), 0 ]) for i in range(n) ] polygon = Polygon(*vertices, color=BLUE) formula = MathTex(r"65537 = 2^{16} + 1") label = Text("正65537边形", font_size=36) formula.move_to(UP * 2.5) label.next_to(formula, DOWN) self.add(polygon, formula, label) self.wait()MathTex使用 LaTeX 语法渲染公式。2^{16}表示 2 的 16 次方。如果你的系统没有安装 LaTeX,这一行会报错,可以改成Text("65537 = 2^16 + 1")。
运行:
manim -pql hex65537.py Hex65537WithText渲染出来的视频画面看起来就是一个蓝色圆形,但左下角或顶部有清晰的公式和名称说明。这个“视觉上是圆,数学上是 65537 个顶点”的反差,就是整个动画最有冲击力的一点。
6. 尺规作图过程的动画拆解
6.1 尺规作图基本动作
真正意义上的尺规作图动画,应该包含两种基本动作:画圆和画直线。在 Manim 中,这分别对应Circle和Line。
先看一个最简单的效果:
from manim import * class BasicCompassAction(Scene): def construct(self): # 定义两个圆心点 A = np.array([-2, 0, 0]) B = np.array([2, 0, 0]) # 画线段 AB segment = Line(A, B, color=WHITE) # 分别以 A、B 为圆心,半径 4 画圆 circle_A = Circle(radius=4, color=YELLOW).move_to(A) circle_B = Circle(radius=4, color=BLUE).move_to(B) self.play(Create(segment)) self.play(Create(circle_A), Create(circle_B)) self.wait()运行:
manim -pql compass_demo.py BasicCompassAction这里展示了尺规作图里最常见的操作:已知一条线段,在线段两端分别作等半径圆,两个圆的交点就是构造新几何对象的关键点。
6.2 演示“过中点作垂线”
两个等圆的交点连线,就是线段 AB 的垂直平分线。这个操作可以如下实现:
class PerpendicularBisector(Scene): def construct(self): A = np.array([-2, 0, 0]) B = np.array([2, 0, 0]) h = np.sqrt(12) # sqrt(4^2 - 2^2) segment = Line(A, B, color=WHITE) circle_A = Circle(radius=4, color=YELLOW).move_to(A) circle_B = Circle(radius=4, color=BLUE).move_to(B) P1 = np.array([0, h, 0]) P2 = np.array([0, -h, 0]) dot_P1 = Dot(P1, color=RED) dot_P2 = Dot(P2, color=RED) bisector = Line(P1, P2, color=GREEN) self.play(Create(segment)) self.play(Create(circle_A), Create(circle_B)) self.play(FadeIn(dot_P1), FadeIn(dot_P2)) self.play(Create(bisector)) self.wait()这里的h = sqrt(12)来自于勾股定理:圆半径是 4,圆心到中点的距离是 2,所以交点到中点的距离是 √(4² − 2²) = √12。
正 17 边形的尺规作图,本质上就是不断重复这种“构造圆交点、连线、取中点、作垂线、开平方”的操作。只不过嵌套层级更多,需要对复数域上的二次方程反复求解。
6.3 从基本操作到正17边形的构造思路
正 17 边形之所以能尺规作图,是因为 17 次单位根可以通过嵌套平方根形式表达:
cos(2π/17) 的表达式大约包含多层根号,具体形式如下:
cos(2π/17) = −1/16 + (√17)/16 + ...
这串长表达式看起来很复杂,但它只包含整数、加减乘除和平方根,正好就是尺规作图能处理的数。因此,理论上我们可以用 Manim 做出一整套“逐步构造正 17 边形”的动画,每一层动画就是一次画圆和连线。
6.4 为什么正65537边形的动画不能逐帧播放
很多人会问:“既然正 17 边形可以逐帧演示构造过程,那正 65537 边形为什么不能?”答案很简单:步骤数量级不一样。
正 17 边形的构造依赖于 4 层二次方程扩张:
φ(17) = 16 = 2^4
正 65537 边形的构造依赖于 16 层二次方程扩张:
φ(65537) = 65536 = 2^16
虽然 16 看起来不大,但每一层都需要在前一层的基础上递归构造大量中间点。赫尔梅斯当年整理出的完整作图方案超过 200 页手稿。就算我们把每个基本操作缩成 1 秒的动画,实际播放时间也远超正常视频长度,更不用说渲染时间和内存消耗。
所以工程上合理的选择是:用 Manim 演示“大边形视觉极限”,再用少量基本动作动画解释“尺规作图逻辑”,而不是强行模拟全程。
7. 常见渲染问题与排查
7.1 常见问题表格
| 问题现象 | 常见原因 | 解决思路 |
|---|---|---|
| manim 命令找不到 | Python Scripts 目录未加入 PATH | 重新安装或把python -m manim作为替代 |
| 渲染视频只有几秒黑屏 | 场景里没有对象或没有self.wait() | 在场景末尾增加self.wait() |
| MathTex 报错 | 系统未安装 LaTeX | 安装 TeX 发行版,或改用Text |
| 中文文字乱码 | 缺少中文字体 | 安装字体,并给Text指定font参数 |
| 65537 边形渲染非常慢 | 顶点数量太大且使用Create | 改用self.add()直接显示 |
| 输出视频卡顿 | 帧率或分辨率过高 | 开发阶段用-ql降低画质 |
| Video 目录为空 | 渲染未完成或代码报错 | 查看终端日志,确认 Scene 类名 |
7.2 渲染慢的具体排查顺序
如果你渲染hex65537.py时感觉卡顿,可以按以下顺序排查:
- 确认是否使用了
Create。如果是,改成self.add()。 - 确认是否设置了过高的
pixel_width和pixel_height。开发阶段建议 854×480。 - 确认
run_time是否设置过大。大数据量图形直接add后wait即可。 - 检查内存占用。如果机器内存小于 8GB,建议关掉其他程序再渲染。
7.3 中文乱码问题处理
如果Text("正65537边形")显示为方框,说明字体缺失。可以手动指定字体:
Text("正65537边形", font="Noto Sans CJK SC", font_size=36)不同系统的字体名不同。Windows 可以尝试Microsoft YaHei,macOS 可以尝试PingFang SC,Linux 可以尝试Noto Sans CJK SC。
8. 最佳实践与工程建议
8.1 把动画场景拆成多个小场景
不要把整个动画写成一个大场景。比如把“展示公式”“绘制正五边形”“对比正十七边形”“渲染正65537边形”分别写成独立的Scene类,再通过 Manim 命令行逐个渲染。这样能避免单场景内存过高,也方便调试。
8.2 大数据量几何对象处理
处理上万级顶点时,建议优先使用数组计算而不是循环。例如:
t = np.arange(n) * TAU / n points = np.zeros((n, 3)) points[:, 0] = radius * np.cos(t) points[:, 1] = radius * np.sin(t)Numpy 批量计算比逐项追加快得多。如果顶点数量达到百万级,甚至可以考虑先用较低分辨率画布渲染,再后期放大。
8.3 数学内容严谨性
在做数学类动画时,务必检查三点:
- 公式是否准确。比如
65537 = 2^16 + 1不能写成2^16 - 1。 - 术语是否规范。比如“费马素数”和“费马数”是不同概念。
- 视频中的每一步构造是否符合几何规则。
如果只是演示视觉极限,文字说明里应该写“数学上可尺规作图”,而不是“上面就是正65537边形的尺规作图全部步骤”。
8.4 输出视频格式与发布建议
Manim 默认输出 MP4。如果你的目标是发到 CSDN 或者 B 站,建议使用-qh渲染最终版,同时保留一个-ql的开发版本。视频分辨率建议 1920×1080,帧率保持默认 15 或 30 均可。
发布到博客时,除了嵌入视频,还可以把运行命令和关键代码段落一起放上去,方便读者复现。这样文章的收藏价值会明显提高。
9. 总结
正 65537 边形从数学上看,是高斯判据下的一个极端案例:边数是费马素数,欧拉函数值是 2 的幂,所以在尺规作图的框架里确实可以构造。但从物理世界来看,它几乎不可能被真正画成一张肉眼可辨认的图,哪怕你有一台运算能力极强的电脑,最终渲染结果也只是一个圆形。
通过 Manim,我们可以用很短的代码把这个“理论可行,实际近似圆形”的数学对象可视化出来。更进一步,我们还能用Circle、Line、Dot这些基础几何对象模拟尺规作图的核心操作,让观众理解复杂的多边形构造思路。
如果你想继续深入,可以尝试:
- 用 Manim 完整演示正 17 边形的尺规作图过程;
- 用动画展示分圆多项式和复数单位根的关系;
- 对比正 3、5、17、257、65537 边形在相同外接圆下的边长收缩趋势;
- 尝试手动实现一个简单的“尺规作图模拟器”,把圆与直线的交点计算逻辑封装起来。
如果本文对你有帮助,欢迎收藏备用。也欢迎在评论区聊聊你自己在用 Manim 做过哪些数学可视化尝试,尤其是那些和数据量、性能有关的“极限场景”。