babylonian_method_animation.py
1from manim import *2import numpy as np3 4config.tex_template = TexTemplateLibrary.ctex5config.tex_template.add_to_preamble(r"\setCJKmainfont{STSong}")6 7class BabylonianMethodAnimation(Scene):8 def construct(self):9 # 标题10 title = Text("巴比伦方法求平方根", font="STSong", font_size=40, color=BLUE)11 self.play(Write(title))12 self.wait(1)13 self.play(FadeOut(title))14 15 # 显示题目(使用数学公式,一行显示)16 problem_title = Text("题目:", font_size=24, color=YELLOW)17 problem_text = MathTex(r"\text{设 } x_0 > 0, x_{n+1} = \frac{1}{2}(x_n + \frac{a}{x_n}), \text{且 } a > 0, \text{证明 } \lim_{n \to \infty} x_n \text{ 存在并求此极限}", font_size=18, color=WHITE)18 19 problem_group = VGroup(problem_title, problem_text).arrange(DOWN, buff=0.2, aligned_edge=LEFT)20 problem_group.to_edge(UP, buff=0.5)21 22 self.play(Write(problem_group))23 self.wait(2)24 25 # 分析思路(左上角)26 analysis_title = Text("分析思路:", font_size=20, color=GREEN)27 analysis_text1 = Text("1. 证明数列单调有界", font_size=16, color=WHITE)28 analysis_text2 = Text("2. 利用单调有界定理", font_size=16, color=WHITE)29 analysis_text3 = Text("3. 求极限值", font_size=16, color=WHITE)30 31 analysis_group = VGroup(analysis_title, analysis_text1, analysis_text2, analysis_text3)32 analysis_group.arrange(DOWN, buff=0.1, aligned_edge=LEFT)33 analysis_group.to_corner(UL, buff=0.3)34 35 self.play(Write(analysis_group))36 self.wait(2)37 38 # 迭代公式分析(移到分析思路下面)39 formula_title = Text("迭代公式分析:", font_size=20, color=ORANGE)40 formula1 = MathTex(r"x_{n+1} = \frac{1}{2}(x_n + \frac{a}{x_n})", font_size=18)41 formula2 = MathTex(r"= \frac{1}{2}(f(x_n) + g(x_n))", font_size=18)42 43 formula_group = VGroup(formula_title, formula1, formula2)44 formula_group.arrange(DOWN, buff=0.15, aligned_edge=LEFT)45 formula_group.to_corner(UL, buff=0.3).shift(DOWN * 1.5)46 47 self.play(Write(formula_group))48 self.wait(2)49 50 # 创建坐标系 - 扩大x轴范围51 axes = Axes(52 x_range=[0, 6, 1], # 从0-4改为0-653 y_range=[0, 4, 1],54 x_length=8, # 从6改为855 y_length=4,56 axis_config={"color": BLUE_B}57 )58 axes.to_edge(RIGHT, buff=0.5).shift(DOWN * 0.5)59 60 # 添加标签61 x_label = axes.get_x_axis_label("x")62 y_label = axes.get_y_axis_label("y")63 64 self.play(Create(axes), Create(x_label), Create(y_label))65 self.wait(1)66 67 # 绘制函数 f(x) = x 和 g(x) = a/x68 a = 2 # 取 a = 2 作为例子69 x_line = axes.plot(lambda x: x, x_range=[0, 5], color=RED) # 从0-3改为0-570 hyperbola = axes.plot(lambda x: a/x, x_range=[0.5, 5], color=GREEN) # 改为[0.5, 5]71 72 # 添加函数标签 - 增大字体73 f_label = MathTex("f(x) = x", color=RED, font_size=20).next_to(x_line, RIGHT, buff=0.1)74 g_label = MathTex("g(x) = \\frac{a}{x}", color=GREEN, font_size=20).next_to(hyperbola, RIGHT, buff=0.1)75 76 self.play(Create(x_line), Create(hyperbola))77 self.play(Write(f_label), Write(g_label))78 self.wait(1)79 80 # 开始迭代过程81 x0 = 5.0 # 初始值改为5.082 iterations = []83 x_values = [x0]84 85 # 在红色直线上标记f(x₀)点86 f_initial_point = Dot(axes.coords_to_point(x0, x0), color=RED, radius=0.06)87 f_initial_label = MathTex("f(x_0)", font_size=14, color=RED).next_to(f_initial_point, UP, buff=0.1)88 89 # 在绿色双曲线上标记g(x₀)点90 g_initial_point = Dot(axes.coords_to_point(x0, a/x0), color=GREEN, radius=0.06)91 g_initial_label = MathTex("g(x_0)", font_size=14, color=GREEN).next_to(g_initial_point, RIGHT, buff=0.1)92 93 self.play(Create(f_initial_point), Write(f_initial_label))94 self.play(Create(g_initial_point), Write(g_initial_label))95 self.wait(1)96 97 # 执行迭代 - 只显示到x498 for i in range(4): # 改为4次迭代99 # 计算下一个值100 x_next = 0.5 * (x_values[-1] + a / x_values[-1])101 x_values.append(x_next)102 103 # 在坐标系中显示迭代过程104 current_x = x_values[-2]105 current_y = x_values[-2]106 107 # 垂直线到双曲线108 vertical_line = DashedLine(109 axes.coords_to_point(current_x, current_y),110 axes.coords_to_point(current_x, a/current_x),111 color=BLUE112 )113 114 # 显示中点计算 - 修正:中点应该是 (x_n, (x_n + a/x_n)/2)115 midpoint_x = current_x116 midpoint_y = (current_x + a/current_x) / 2117 midpoint_point = Dot(axes.coords_to_point(midpoint_x, midpoint_y), color=PURPLE_A, radius=0.05)118 119 # 显示具体的迭代公式120 midpoint_label = MathTex(f"x_{i+1} = \\frac{{1}}{{2}}(x_{i} + \\frac{{a}}{{x_{i}}})", font_size=12, color=PURPLE_A)121 122 # 根据迭代次数调整公式标签位置123 if i == 3: # x₄的情况,显示在交点下方124 midpoint_label.next_to(midpoint_point, DOWN, buff=0.1)125 else:126 midpoint_label.next_to(midpoint_point, RIGHT)127 128 # 从紫色中点直接连线到x轴上的下一个迭代点位置129 horizontal_line = DashedLine(130 axes.coords_to_point(midpoint_x, midpoint_y),131 axes.coords_to_point(x_next, 0), # 连线到x轴上的x_{i+1}位置132 color=PURPLE_A133 )134 135 # 在x轴上标记下一个迭代点位置136 x_axis_point = Dot(axes.coords_to_point(x_next, 0), color=YELLOW, radius=0.05)137 x_axis_label = MathTex(f"x_{i+1}", font_size=14, color=YELLOW).next_to(x_axis_point, DOWN, buff=0.1)138 139 # 从x轴上的点向上做垂直线找到f(x_{i+1})和g(x_{i+1})140 vertical_line_to_f = DashedLine(141 axes.coords_to_point(x_next, 0),142 axes.coords_to_point(x_next, x_next),143 color=RED144 )145 146 vertical_line_to_g = DashedLine(147 axes.coords_to_point(x_next, 0),148 axes.coords_to_point(x_next, a/x_next),149 color=GREEN150 )151 152 # 在红色直线上标记f(x_{i+1})点153 f_next_point = Dot(axes.coords_to_point(x_next, x_next), color=RED, radius=0.06)154 f_next_label = MathTex(f"f(x_{i+1})", font_size=14, color=RED)155 156 # 在绿色双曲线上标记g(x_{i+1})点157 g_next_point = Dot(axes.coords_to_point(x_next, a/x_next), color=GREEN, radius=0.06)158 g_next_label = MathTex(f"g(x_{i+1})", font_size=14, color=GREEN)159 160 # 根据迭代次数调整标签位置,避免与交点重叠161 if i == 3: # x₄的情况162 f_next_label.next_to(f_next_point, LEFT, buff=0.1)163 g_next_label.next_to(g_next_point, LEFT, buff=0.1)164 else:165 f_next_label.next_to(f_next_point, UP, buff=0.1)166 g_next_label.next_to(g_next_point, RIGHT, buff=0.1)167 168 self.play(Create(vertical_line))169 self.wait(0.5)170 self.play(Create(midpoint_point), Write(midpoint_label))171 self.wait(1)172 self.play(Create(horizontal_line))173 self.wait(0.5)174 self.play(Create(x_axis_point), Write(x_axis_label))175 self.wait(0.5)176 self.play(Create(vertical_line_to_f), Create(vertical_line_to_g))177 self.wait(0.5)178 self.play(Create(f_next_point), Write(f_next_label))179 self.play(Create(g_next_point), Write(g_next_label))180 self.wait(1)181 182 # 显示收敛性证明(移到迭代分析下面)183 proof_title = Text("收敛性证明:", font_size=20, color=PURPLE)184 proof1 = MathTex(r"1. \text{下界性:} x_n \geq \sqrt{a}", font_size=16)185 proof2 = MathTex(r"2. \text{单调性:} x_{n+1} \leq x_n", font_size=16)186 proof3 = MathTex(r"3. \text{极限:} \lim_{n \to \infty} x_n = \sqrt{a}", font_size=16)187 188 proof_group = VGroup(proof_title, proof1, proof2, proof3)189 proof_group.arrange(DOWN, buff=0.1, aligned_edge=LEFT)190 proof_group.to_corner(UL, buff=0.3).shift(DOWN * 3.5)191 192 self.play(Write(proof_group))193 self.wait(2)194 195 # 显示数值结果196 result_title = Text("数值结果:", font_size=24, color=YELLOW)197 result_text = Text(f"a = {a}, x₀ = {x0}", font_size=18, color=WHITE)198 199 result_group = VGroup(result_title, result_text)200 result_group.arrange(DOWN, buff=0.2, aligned_edge=LEFT)201 result_group.to_edge(LEFT, buff=0.5).shift(DOWN * 5.5)202 203 self.play(Write(result_group))204 self.wait(2)205 206 # 最终结论(移到最下面)207 conclusion_title = Text("结论:", font_size=24, color=GREEN)208 conclusion1 = MathTex(r"\lim_{n \to \infty} x_n = \sqrt{a}", font_size=24, color=YELLOW)209 conclusion2 = Text("这是求平方根的巴比伦方法", font_size=20, color=WHITE)210 211 conclusion_group = VGroup(conclusion_title, conclusion1, conclusion2)212 conclusion_group.arrange(DOWN, buff=0.3, aligned_edge=LEFT)213 conclusion_group.to_corner(DL, buff=0.5)214 215 # 突出显示最终结果216 result_box = SurroundingRectangle(conclusion1, buff=0.2, color=YELLOW)217 218 self.play(Write(conclusion_group))219 self.play(Create(result_box))220 self.wait(3)221 222if __name__ == "__main__":223 # 使用1080p渲染设置224 config.frame_rate = 30225 config.pixel_width = 1920226 config.pixel_height = 1080227 scene = BabylonianMethodAnimation()228 scene.render() 讲解
这个视频围绕「巴比伦法求平方根」展开。画面把问题、图像和公式放在同一条理解路径中,让抽象关系先被看见。
开头先建立问题背景和主要对象,让观察从标题、坐标或第一组关系进入。
画面中出现的文字「巴比伦方法求平方根」给出视觉入口。随后画面通过对象创建、移动、淡入淡出和高亮,把抽象命题拆成可以跟随的步骤。
随后出现更具体的图像或公式提示,动画会把局部对象和整体结论联系起来。这里可以重点观察变量、曲线、区域或向量如何随镜头推进而变化。
核心公式可以写成:
这类公式可以和画面中的符号一一对应。
观察路径
观察路径可以分三步:先锁定「巴比伦法求平方根」中的核心对象,尤其留意巴比伦开方法、单调有界原理、数列收敛之间的联系;再跟随画面中变量、图像或向量的变化;最后回到公式或结论,判断局部变化如何支撑整体关系。
本页可以从巴比伦开方法、单调有界原理、数列收敛、迭代法这些概念进入,继续沿相邻问题观察同一类数学结构。