资讯动态

Manim动画实战:正65537边形与尺规作图的数学原理

发布时间:2026/9/7 10:47:31 来源:尧图企业网站定制
看到这个标题先别急着划走。正 65537 边形一个听起来就让人头皮发麻的数字。如果真按字面意思把尺规作图的每一个命令步骤都画成动画那这期视频大概要连续播放几天几夜——因为早在 19 世纪末数学家赫尔梅斯J. G. Hermes就曾为正 65537 边形的尺规作图方案耗费了约十年时间他整理出的手稿据说有 200 多页厚得可以直接当枕头。所以本文真正要做的不是去逐条复现那份庞杂的手稿而是换一条更务实也更硬核的路线用 Manim 动画把“正 65537 边形为什么能用尺规作图”背后的数学原理讲清楚再通过程序化方式模拟“把圆等分成 65537 份”的完整视觉过程。无论你是对 Manim 感兴趣的 Python 开发者还是想理解尺规作图极限问题的数学爱好者这篇文章都能给你一套从环境搭建到代码实现、再到性能调优的完整方案。读完你会明白所谓“尺规作图的癫疯”到底疯在哪里。1. 背景正65537边形为什么值得折腾1.1 一个让尺规作图走到极限的问题尺规作图是数学里最古老也最优雅的约束之一只能使用没有刻度的直尺和圆规在有限步操作内完成几何构造。直线和圆看似简单却能构造出极其复杂的图形。正三角形、正方形、正五边形、正六边形这些都是课本里就有的内容正十七边形已经让许多人觉得不可思议而正 65537 边形听起来几乎是一种“数学挑衅”。之所以说它值得折腾是因为它的边数非常特殊65537 2^16 1这是一个费马素数。在尺规作图的判定体系里正 n 边形可作图的条件非常苛刻而 65537 正是目前已知最大的、能直接以素数身份参与构造正多边形的费马素数。这意味着理论上你确实可以用一把直尺和一个圆规经过有限次操作构造出一个边数多达六万五千五百三十七的正多边形。这个结论和人类的直觉完全相反——六万多条边肉眼看上去和圆已经没有任何区别了它怎么还能被精确构造出来1.2 可作图数的秘密要理解这个问题需要先把尺规作图翻译成代数问题。在平面直角坐标系中如果给定一段单位长度那么尺规作图能得到的所有点坐标都可以看作是从有理数出发通过有限次的加、减、乘、除以及开平方运算得到的数值。为什么这么说因为尺规作图的本质就是求交直线与直线相交对应的是解线性方程直线与圆相交、圆与圆相交对应的是解二次方程。二次方程会引入平方根而反复解二次方程就相当于反复开平方。所以一个几何对象能否用尺规作出在代数上就转化为“它对应的数能否用有限次四则运算和开平方构造出来”。这个观点非常重要。它把几何难题变成了代数难题也直接引出了高斯关于正多边形可作图性的著名定理一个正 n 边形可以尺规作图当且仅当 n 的欧拉函数 φ(n) 是 2 的幂。换句话说n 必须能写成 2 的幂次乘以若干个互不相同的费马素数。正 65537 边形满足这个条件所以它理论上一定能被尺规作图。1.3 高斯定理与费马素数费马素数形如 F_t 2^(2^t) 1。前几个费马数是tF_t 的值是否为素数03是15是217是3257是465537是54294967297否能被 641 整除费马最初猜想所有这类数都是素数但欧拉很快发现 F_5 可以被 641 整除这个猜想就被推翻了。目前已知的费马素数只有前五个其中 65537 是最大的一个。这也是正 65537 边形在尺规作图理论里如此特殊的原因当边数是费马素数时分圆多项式能够通过有限次二次方程分解来完成构造而 65537 又是目前可用的“最大单块积木”。1.4 动画里的“完整过程”是什么口径这里必须诚实说明一个口径问题所谓“完整过程”在动画里不可能真的把赫尔梅斯手稿中的几千步尺规操作逐条画出来。赫尔梅斯的方法涉及大量根式扩张和中间辅助点每一步都需要极精确的几何关系如果全部可视化不仅动画时长不可控观看体验也会极其糟糕。因此本文采用的策略是“数学等价过程”正 n 边形由圆周上的 n 个等分点决定而 n 个等分点对应的是“把圆心角 2π 等分成 n 份”这一数学事实。Manim 程序可以直接根据这个事实生成多边形并用边数从 3、5、17、257 到 65537 的渐进过程让观众直观看到“边数越多图形越接近圆”。这种演示虽然不逐条复现尺规命令但它准确传达了“为什么可作图”的核心逻辑也更适合做成视频传播。2. Manim 环境准备2.1 为什么选择 Manim Community EditionManim 是 3Blue1Brown 开发的数学动画引擎但官方仓库的版本并不适合普通用户直接使用。目前社区维护的 Manim Community Edition简称 manimce是最主流的选择它把安装方式、API 设计和文档都整理得非常规范直接用pip install manim就能安装。本文所有代码都基于 Manim Community Edition 编写如果你使用的是其他分支版本部分 API 可能需要微调。建议在 Python 3.9 以上的环境中运行。如果你已经有多个 Python 项目并存最好为这个数学动画项目单独创建一个虚拟环境避免依赖冲突。2.2 安装 Manim创建并激活虚拟环境后执行以下命令安装 Manimpython -m venv manim-env source manim-env/bin/activate pip install --upgrade pip pip install manimWindows 用户激活虚拟环境的命令是manim-env\Scripts\activate。安装完成后可以运行manim --version确认版本号正常输出。如果出现找不到命令的情况请检查虚拟环境是否已激活或者 Python 的 Scripts 目录是否加入了 PATH。2.3 安装系统依赖Manim 运行还需要两个系统级依赖FFmpeg 和 Pango。FFmpeg 用于把渲染出的帧合成视频如果缺少它会直接报错。Pango 则用于文本渲染Manim 中的Text对象依赖它来显示文字。不同操作系统的安装方式不同# Ubuntu / Debian sudo apt update sudo apt install ffmpeg libpango1.0-dev # macOS brew install ffmpeg pango # Windows winget install ffmpegWindows 用户安装完成后需要确认 FFmpeg 已经加入 PATH例如在命令行执行ffmpeg -version能看到版本信息。如果你不需要在动画里显示中文Pango 一般不会成为问题但 FFmpeg 是刚需。2.4 项目初始化建议按下面的结构创建项目目录manim-65537/ ├── main.py ├── requirements.txt └── media/requirements.txt可以写成manim numpy由于 Manim 社区版本身就依赖 numpy第二行其实可以省略但写出来更明确。media目录会在首次渲染时自动生成不需要手动创建。接下来所有的动画场景都会写在main.py中。3. 正65537边形的数学原理拆解3.1 用坐标刻画正 n 边形在程序里生成正多边形最直接的方法是利用三角函数。设圆心在原点半径为 r那么正 n 边形的第 k 个顶点坐标是x_k r * cos(2π * k / n) y_k r * sin(2π * k / n)其中 k 从 0 到 n-1。这个公式看起来简单但它背后正是尺规作图可构造性的代数核心当 n 是费马素数时这些三角函数值可以通过有限次二次方程求解得到因而对应的点坐标也能通过尺规作图得到。程序直接调用三角函数本质上是把这个代数过程“黑盒化”了这也是为什么我们能在动画里快速画出 65537 边形而真实作图却要耗费一沓手稿。3.2 从正十七边形到正65537边形1796 年19 岁的高斯发现了正十七边形的尺规作图方法这是数学史上非常著名的故事。高斯证明了正十七边形可作图随后又给出了可作图正多边形的完整判别条件也就是前面提到的 φ(n) 为 2 的幂。正十七边形已经非常接近圆肉眼几乎看不出它是多边形正 257 边形基本上就是“圆”的替身而正 65537 边形放在屏幕上连一个像素的误差都很难察觉。但这并不代表 65537 边形没有意义。理论价值恰恰体现在“构造难度”上从正十七边形到正 257 边形再到正 65537 边形每跨一步所需的二次扩张层数和辅助构造步骤都会爆炸式增长。赫尔梅斯之所以花十年时间就是因为越大的费马素数对应的构造方案越庞大这种“理论可行”与“人类做不到”之间的张力正是这个题目最有魅力的地方。3.3 肉眼差距一张表看清楚为了直观感受不同边数的视觉效果把中心角列出来边数 n每个中心角视觉效果3120°明显的三角形17≈ 21.18°接近圆但边缘仍有棱角257≈ 1.40°基本是圆65537≈ 0.0055°与圆完全重合从这张表能明显看出边数超过 257 后视觉差异已经不存在了。所以动画项目里模拟 65537 边形的意义更多在于“原理呈现”而不是“外形差异”。3.4 从“作图步骤”到“动画模拟”这里再强调一次Manim 项目模拟的并不是赫尔梅斯手稿中每一步尺规操作而是“正 n 边形作为圆周等分结果”的最终形态。也就是说程序通过公式直接生成顶点再用动画展示边数递增时多边形与圆的关系。这种方式在数学科普里非常常见它牺牲了“步骤级还原度”但换来了极高的表达效率和视觉冲击力。如果你未来想挑战真正的步骤级动画那需要先做大量几何关系整理再设计上千个 Mobject 的联动工程量和篇幅会远超本文范围。4. 用 Manim 实现基础多边形动画4.1 第一个场景从圆开始先来看一个最简单的例子画一个圆然后在圆上生成一个正六边形。我们先用这个场景确认 Manim 环境是否正常。# 文件路径main.py from manim import * import numpy as np def regular_polygon_points(n, radius2.0, centerORIGIN): points [] for k in range(n): angle k * TAU / n x center[0] radius * np.cos(angle) y center[1] radius * np.sin(angle) points.append(np.array([x, y, 0.0])) return points class SimplePolygon(Scene): def construct(self): circle Circle(radius2.0, colorBLUE_D) self.play(Create(circle), run_time1.5) pts regular_polygon_points(6, radius2.0) poly Polygon(*pts, colorYELLOW, stroke_width3) self.play(Create(poly), run_time2) label Text(n 6, font_size36).next_to(poly, DOWN) self.play(FadeIn(label)) self.wait(1)这段代码做了四件事先创建半径为 2 的蓝色圆形再用regular_polygon_points计算正六边形的六个顶点通过Polygon(*pts)生成闭合多边形最后在图形下方显示标签n 6。TAU在 Manim 中等于2π用它可以避免手写数字 6.28318。运行命令是manim -pql main.py SimplePolygon如果一切正常会播放一段约 5 秒的动画最后画面中央是一个蓝色圆和黄色正六边形。4.2 正多边形顶点计算regular_polygon_points函数是整篇文章的基础。它接受三个参数边数n、半径radius、圆心center。循环内部用TAU / n计算出每个顶点对应的圆心角再用 cos 和 sin 换算成坐标。这里有一个容易被忽略的点直接让多边形顶点从 0 度开始意味着第一条边是水平方向的。为了让多边形在视觉上更对称可以给角度加一个偏移量比如从TAU / 4或PI / 2开始。不过本文所有示例为了让代码最简单都不加偏移这不影响数学演示。4.3 显示正十七边形有了顶点计算函数显示正十七边形只是改一个参数的事。下面这个场景会在圆上生成正十七边形并显示出文字标签。class FromSeventeen(Scene): def construct(self): circle Circle(radius2.2, colorBLUE_D) self.play(Create(circle), run_time1.5) n 17 pts regular_polygon_points(n, radius2.2) poly Polygon(*pts, colorYELLOW, stroke_width2) self.play(Create(poly), run_time2) label Text(fregular n-gon: n {n}, font_size32).next_to(poly, DOWN) self.play(FadeIn(label)) self.wait(1)运行这个场景manim -pql main.py FromSeventeen你会看到正十七边形已经非常接近圆形但边缘仍能感受到微弱的棱角。这个场景非常适合作为后续大边数演示的对比基线。5. 模拟正65537边形的构造过程5.1 渐进式替换演示模拟 65537 边形的核心思路是让观众看到边数从 17 到 257 再到 65537 的连续变化。直接给出一张 65537 边形的图并不震撼震撼的是“原来它与圆如此接近”。下面这个场景会依次展示 17、257、65537 三种正多边形并用标签提示当前边数。class BigPolygonApproximation(Scene): def construct(self): circle Circle(radius2.0, colorBLUE_D) self.add(circle) steps [17, 257, 65537] for n in steps: pts regular_polygon_points(n, radius2.0) poly Polygon(*pts, colorYELLOW, stroke_width1) label Text(fn {n}, font_size36).next_to(ORIGIN, DOWN) self.play(FadeIn(poly), run_time1.0) self.play(FadeIn(label)) self.wait(1.0) if n ! steps[-1]: self.play(FadeOut(poly), FadeOut(label)) else: self.wait(1.0)运行命令manim -pql main.py BigPolygonApproximation在最终画面中65537 边形会呈现为一个几乎完美的圆但下方标签清晰显示n 65537。这个“视觉上的圆 数学上的多边形”组合就是整期动画最核心的冲击点。5.2 为什么不能用 Create 画 65537 边形如果你把上面代码中的FadeIn(poly)换成Create(poly)就会发现在渲染 65537 边形时程序会明显卡顿甚至长时间没有反应。原因在于Create动画会逐点绘制 Mobject 的路径而Polygon内部包含 65537 个顶点的路径数据。逐点绘制意味着要经历几万次路径更新Cairo 渲染器会不堪重负。FadeIn则完全不同它只需要在有限帧内改变整体的透明度不涉及每个顶点的逐个出现因此性能开销要小得多。这也是工程上很重要的一个经验大数据量几何对象不要让动画逐点执行尽量整体淡入、淡出或直接切换。5.3 角平分思想的动画抽象尺规作图里等分圆周的核心操作是构造角度而角度二分是最基础的尺规动作。虽然我们无法在动画里逐步执行赫尔梅斯的上千次操作但可以做一个“角平分思想”的抽象演示先画出两条相邻半径再画出它们夹角的中线表示一次等分过程。class AngleBisection(Scene): def construct(self): center ORIGIN radius 2.5 angle TAU / 3 p1 np.array([radius, 0, 0]) p2 np.array([radius * np.cos(angle), radius * np.sin(angle), 0]) pmid np.array([radius * np.cos(angle / 2), radius * np.sin(angle / 2), 0]) line1 Line(center, p1, colorWHITE) line2 Line(center, p2, colorWHITE) bisector Line(center, pmid, colorYELLOW, stroke_width5) self.play(Create(line1), Create(line2)) self.play(Create(bisector)) label Text(angle bisection, font_size30).next_to(bisector, DOWN) self.play(FadeIn(label)) self.wait(1)运行命令manim -pql main.py AngleBisection这个场景展示的是“从一条半径到另一条半径之间的角平分线”它是尺规作图中反复出现的核心动作。如果你后续想深入赫尔梅斯的真实构造过程可以从这个动作出发把所有辅助点拆解成角平分和作垂线的组合再交给 Manim 的 Updater 机制逐帧驱动。6. 完整项目代码6.1 main.py 完整代码为了让读者可以直接复制运行我把上述场景全部整合到一个文件中。文件路径是main.py。# 文件路径main.py from manim import * import numpy as np def regular_polygon_points(n, radius2.0, centerORIGIN): 生成正 n 边形顶点坐标 points [] for k in range(n): angle k * TAU / n x center[0] radius * np.cos(angle) y center[1] radius * np.sin(angle) points.append(np.array([x, y, 0.0])) return points class SimplePolygon(Scene): def construct(self): circle Circle(radius2.0, colorBLUE_D) self.play(Create(circle), run_time1.5) pts regular_polygon_points(6, radius2.0) poly Polygon(*pts, colorYELLOW, stroke_width3) self.play(Create(poly), run_time2) label Text(n 6, font_size36).next_to(poly, DOWN) self.play(FadeIn(label)) self.wait(1) class FromSeventeen(Scene): def construct(self): circle Circle(radius2.2, colorBLUE_D) self.play(Create(circle), run_time1.5) n 17 pts regular_polygon_points(n, radius2.2) poly Polygon(*pts, colorYELLOW, stroke_width2) self.play(Create(poly), run_time2) label Text(fregular n-gon: n {n}, font_size32).next_to(poly, DOWN) self.play(FadeIn(label)) self.wait(1) class BigPolygonApproximation(Scene): def construct(self): circle Circle(radius2.0, colorBLUE_D) self.add(circle) steps [17, 257, 65537] for n in steps: pts regular_polygon_points(n, radius2.0) poly Polygon(*pts, colorYELLOW, stroke_width1) label Text(fn {n}, font_size36).next_to(ORIGIN, DOWN) self.play(FadeIn(poly), run_time1.0) self.play(FadeIn(label)) self.wait(1.0) if n ! steps[-1]: self.play(FadeOut(poly), FadeOut(label)) else: self.wait(1.0) class AngleBisection(Scene): def construct(self): center ORIGIN radius 2.5 angle TAU / 3 p1 np.array([radius, 0, 0]) p2 np.array([radius * np.cos(angle), radius * np.sin(angle), 0]) pmid np.array([radius * np.cos(angle / 2), radius * np.sin(angle / 2), 0]) line1 Line(center, p1, colorWHITE) line2 Line(center, p2, colorWHITE) bisector Line(center, pmid, colorYELLOW, stroke_width5) self.play(Create(line1), Create(line2)) self.play(Create(bisector)) label Text(angle bisection, font_size30).next_to(bisector, DOWN) self.play(FadeIn(label)) self.wait(1)6.2 运行命令渲染单个场景使用下面的命令。-p表示渲染完成后自动预览-q l表示低质量档速度更快想导出高质量视频可以把l换成h。manim -pql main.py SimplePolygon manim -pql main.py FromSeventeen manim -pql main.py BigPolygonApproximation manim -pql main.py AngleBisection如果你只需要一张最终画面作为封面或文章配图可以使用-s参数只渲染最后一帧manim -s -qk main.py BigPolygonApproximation-s会生成一张 PNG 图片默认放在media/images/main/目录下。6.3 预期输出正常渲染后media/videos/main/目录下会生成对应的 mp4 文件。每个场景对应一个独立视频文件名通常以场景类名结尾。其中BigPolygonApproximation这个场景的最终画面尤其适合作为视频封面背景是蓝色圆中心区域是一个与实际圆几乎重合的黄色正 65537 边形底部显示n 65537的标签。这里需要注意如果电脑内存不足渲染 65537 边形时可能出现卡顿建议先尝试将steps列表中的 65537 改为 4096 或 1024 跑通流程再逐步增加。7. 常见问题与排查思路7.1 高频问题表下面是这个项目里最常见的几类问题建议优先对照排查问题现象常见原因解决思路安装 manim 很慢或超时网络源不稳定或依赖包较多使用国内 pip 镜像例如-i https://pypi.tuna.tsinghua.edu.cn/simple运行 manim 提示找不到 ffmpeg系统没有安装 FFmpeg或未加入 PATH按操作系统安装 FFmpeg并在命令行验证ffmpeg -version动画中的中文文字变成方块系统缺少对应字体或 Pango 字体配置不正确改用英文标签或使用Text(..., fontNoto Sans CJK SC)指定已有字体渲染 65537 边形卡顿或内存溢出Mobject 顶点过多动画逐点执行用FadeIn代替Create降低演示边数先渲染静态帧使用MathTex报错找不到 latex系统没有安装 LaTeX 发行版安装 TeXLive / MiKTeX或改用Text显示简单文本多边形边缘被平滑成曲线调用了set_points_smoothly或类似方法检查代码使用Polygon默认的折线路径不要做平滑插值7.2 两个典型排错过程第一个典型问题是“安装成功但运行报错没有 ffmpeg”。许多新手明明执行了pip install manim却在渲染时看到FFmpeg not found。原因通常是系统里根本没有 FFmpeg 这个程序Manim 只是把它作为外部工具调用。解决方案不是重复pip install而是去官网下载 FFmpeg 并加入 PATH或者用系统包管理器安装。安装完成后重新打开终端确认ffmpeg -version能正常输出。第二个典型问题是“渲染 BigPolygonApproximation 时内存飙升”。这个问题的根源是Polygon在内部把每个顶点都加入路径65537 个顶点会生成非常庞大的数据结构。如果你还把动画设置成CreateManim 还会逐点更新CPU 占用会立刻拉满。解决办法很简单对大边数多边形使用FadeIn和FadeOut避免逐点动画如果内存仍然不足就用静态帧-s渲染成品图效果完全一样。8. 最佳实践与工程建议8.1 数学表达要严谨做数学动画很容易踩的一个坑是把“程序模拟”和“数学真实”混为一谈。比如本文的项目程序是用三角函数直接算出 65537 个顶点这并不等于“用尺规完成了作图”。为了不误导观众动画里建议加上“simulation / 模拟”字样的标签或者在视频简介里明确说明这里展示的是等价结果不是真实作图过程。严谨的数学表达是这类视频内容能长期传播的基础。8.2 Manim 性能优化如果你以后想做大边数多边形动画有几条性能经验可以复用大量顶点的对象尽量静态化不要在construct里反复重建。对复杂 Mobject 使用FadeIn代替Create避免逐点绘制。能用静态帧解决的封面图不要硬合成视频。渲染时先用低质量档-ql验证动画逻辑再用高质量档输出最终视频。如果内存确实不够可以放弃实时动画改为预先计算所有顶点坐标再通过set_points一次性写入路径。这些建议对任何包含高分辨率几何对象的 Manim 项目都适用不只是 65537 边形。8.3 文本与字体选择Manim 的Text对象依赖 Pango不同系统字体名称不同。如果需要在动画里显示中文建议先确认系统已安装中文字体然后显式指定字体名Text(正65537边形, fontNoto Sans CJK SC, font_size36)如果你在 macOS 上可能需要换成PingFang SC或Hiragino Sans GB。为了避免跨平台字体问题本文示例代码统一使用英文标签运行成本最低。如果想在动画里展示漂亮的上标公式比如 (2^{16}1)可以安装 LaTeX 后改用MathTex效果会更专业。8.4 工程化管理如果你准备把这个项目扩展成系列视频建议做好工程化管理使用requirements.txt固定 Manim 版本避免未来升级导致接口变化。把media/目录加入.gitignore渲染产物体积很大不适合提交到代码仓库。在main.py顶部用注释写清楚每个场景的作用和运行命令方便以后复用。数学推导过程单独写一个notes.md把费马素数、高斯定理、多边形顶点公式都整理进去方便校对。这样即使过半年再回来改动画也能快速找回上下文。9. 总结与下一步学习路线本文从正 65537 边这个特殊边数出发拆解了尺规作图的代数判定条件解释了费马素数与可作图正多边形的关系并基于 Manim Community Edition 完成了一套从环境搭建到代码实现、再到性能调优的完整动画项目。你现在应该已经掌握两点核心内容第一正 65537 边形之所以可作图是因为 65537 是费马素数满足高斯定理第二用 Manim 展示大边数多边形时要合理选择动画方式避免逐点绘制造成性能瓶颈。下一步可以尝试三个方向一是自己做一个正十七边形的高斯作图动画这是所有尺规作图动画里的经典题材二是深入学习分圆多项式和伽罗瓦理论理解高斯的判定定理为什么成立三是研究 Manim 的 Updater 机制把角平分、作垂线等基础尺规动作封装成可复用的动画函数为未来实现更复杂的几何构造做准备。如果你也想做一期让同学和读者眼前一亮的数学动画建议先从 17 边形开始再挑战 257 边形最后才上 65537。直接上 65537视觉上是震撼工程上就是在测试渲染器和电脑内存的极限了。希望这篇教程能帮你顺利迈出第一步。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价