news 2026/9/7 16:49:42

尺规作图极限:用Manim动画演示正65537边形的数学原理与实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
尺规作图极限:用Manim动画演示正65537边形的数学原理与实现

如果你的首页刷到过《【全网首个】尺规作图正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 --version

3.2 依赖项说明

Manim 渲染需要以下几个外部程序:

依赖作用说明
Python 3.8+运行环境Manim 依赖 Python 3.8 及以上版本
FFmpeg视频编码不安装会无法导出 mp4
LaTeX(可选)渲染数学公式不带 LaTeX 也能用部分文本,但 MathTex 依赖它
Cairo / Pango字体和图形渲染pip 安装 manim 时会自动处理

FFmpeg 的安装方式根据操作系统有所不同。macOS 可以用:

brew install ffmpeg

Ubuntu 可以用:

sudo apt install ffmpeg

Windows 用户建议从 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 PentagonDemo

4.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.mp4

480p15表示低画质 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 Hex65537Visual

5.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 中,这分别对应CircleLine

先看一个最简单的效果:

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时感觉卡顿,可以按以下顺序排查:

  1. 确认是否使用了Create。如果是,改成self.add()
  2. 确认是否设置了过高的pixel_widthpixel_height。开发阶段建议 854×480。
  3. 确认run_time是否设置过大。大数据量图形直接addwait即可。
  4. 检查内存占用。如果机器内存小于 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,我们可以用很短的代码把这个“理论可行,实际近似圆形”的数学对象可视化出来。更进一步,我们还能用CircleLineDot这些基础几何对象模拟尺规作图的核心操作,让观众理解复杂的多边形构造思路。

如果你想继续深入,可以尝试:

  • 用 Manim 完整演示正 17 边形的尺规作图过程;
  • 用动画展示分圆多项式和复数单位根的关系;
  • 对比正 3、5、17、257、65537 边形在相同外接圆下的边长收缩趋势;
  • 尝试手动实现一个简单的“尺规作图模拟器”,把圆与直线的交点计算逻辑封装起来。

如果本文对你有帮助,欢迎收藏备用。也欢迎在评论区聊聊你自己在用 Manim 做过哪些数学可视化尝试,尤其是那些和数据量、性能有关的“极限场景”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 16:49:32

新媒体博主报价表怎么做?从定价逻辑到避坑实战全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 16:49:06

把TCP三次握手讲成网恋奔现,面试直接稳了

上个月去面一家做网络设备的中厂&#xff0c;技术面第二轮&#xff0c;面试官是个看起来三十出头、话不多的老哥。他翻了翻简历&#xff0c;抬头问了一句&#xff1a;“TCP三次握手为什么不设计成两次&#xff1f;”我脑子里条件反射冒出来的是RFC 793、SYN队列、ISN随机化这些…

作者头像 李华
网站建设 2026/9/7 16:48:58

C++解释器模式变体:从AST遍历到字节码栈机的工程实践

聊到解释器模式&#xff0c;很多人第一反应是GoF那本《设计模式》里表达式求值的经典示例&#xff1a;一个抽象Expression&#xff0c;一个TerminalExpression&#xff0c;一个NonterminalExpression&#xff0c;然后递归求值。这个例子在教科书里足够清晰&#xff0c;但放到真…

作者头像 李华
网站建设 2026/9/7 16:43:09

AI 测试进阶路线:从 pytest 自动化到大模型效果评估

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华